home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / Pascal / Applications / NIH Image 1.62b11 / src / File2.p < prev    next >
Text File  |  1997-05-13  |  84KB  |  3,021 lines

  1. unit File2;
  2.  
  3. {Routines used by NIH Image for printing plus a few additional File Menu routines.}
  4.  
  5. interface
  6.  
  7.  
  8.     uses
  9.         Types, Memory, QuickDraw, QuickDrawText, Packages, Menus, Events, Fonts, Scrap, ToolUtils, Resources,
  10.         Errors, Palettes, Printing, StandardFile, Folders, TextUtils, Dialogs, Files, Finder, Script,
  11.         globals, Utilities, Graphics, Lut, PictUtils, QDOffscreen, Components, ImageCompression,
  12.         Movies, QuickTimeComponents, Sound, FixMath, GestaltEqu;
  13.  
  14.  
  15.     procedure GetInfo;
  16.     procedure DoPageSetup;
  17.     procedure Print (ShowDialog: boolean);
  18.     procedure SetHalftone;
  19.     function OpenMacPaint (fname: str255; vnum: integer): boolean;
  20.     procedure TypeMismatch (fname: str255);
  21.     function GetTextFile (var name: str255; var RefNum: integer): boolean;
  22.     procedure InitTextInput (name: str255; RefNum: integer);
  23.     procedure GetLineFromText (var rLine: RealLine; var count: integer);
  24.     function ImportTextFile (name: str255; RefNum: integer): boolean;
  25.     procedure PlotXYZ;
  26.     procedure SaveSettings;
  27.     procedure ExportAsText (fname: str255; RefNum: integer);
  28.     procedure ExportMeasurements (fname: str255; RefNum: integer);
  29.     function OpenTiffHeader (f: integer; var DirOffset: LongInt): boolean;
  30.     function OpenTiffDirectory (f: integer; DirOffset: LongInt; var TiffInfo: TiffInfoRec; Importing: boolean): boolean;
  31.     procedure SaveTiffColorMap (f: integer; ImageDataSize: LongInt);
  32.     procedure GetTiffColorMap (f: integer);
  33.     function SaveTiffDir (f, slines, sPixelsPerLine: integer; SavingSelection: boolean; ctabSize, ImageDataSize: LongInt): OSErr;
  34.     function RoomForFile (fname: str255; RefNum: integer; slines, sPixelsPerLine: integer; SavingSelection: boolean): boolean;
  35.     function WriteExtraTiffIFDs (f: integer; ImageDataSize, cTabSize: LongInt): integer;
  36.     procedure SaveLUT (fname: str255; RefNum: integer);
  37.     procedure SaveColorTable (fname: str255; RefNum: integer);
  38.     procedure ExportCoordinates (fname: str255; RefNum: integer);
  39.     procedure SaveOutline (fname: str255; RefNum: integer);
  40.     procedure OpenOutline (fname: str255; RefNum: integer);
  41.     function CheckIO (err: OSerr): integer;
  42.     function GetTIFFParameters (name: str255; RefNum: integer; var HasColorMap: boolean): boolean;
  43.     procedure GetXUnits (UnitsKind: UnitsType);
  44.     procedure GetUnitsKInd (var UnitsKind: UnitsType; var UnitsPerCM: extended);
  45.     procedure Swap2Bytes (var i: integer);
  46.     procedure Swap4Bytes (var i: LongInt);
  47.     function OpenQuickTime (name: str255; fRefNum: integer; UseExistingLUT: boolean): boolean;
  48.     procedure SaveAsQuickTime (fname: str255; fRefNum: integer);
  49.     function OpenMovieToolbox:boolean;
  50.  
  51.  
  52. implementation
  53.  
  54.     var
  55.         gstr: str255;
  56.         
  57.  
  58. {$PUSH}
  59. {$D-}
  60.  
  61.     procedure PrintErrCheck;
  62.         var
  63.             err: integer;
  64.             ticks: LongInt;
  65.     begin
  66.         err := PrError;
  67.         if err < 0 then
  68.             beep;
  69.     end;
  70.  
  71.  
  72.     procedure DoPageSetup;
  73.         var
  74.             result: boolean;
  75.     begin
  76.         PrOpen;
  77.         if PrintRecord = nil then begin
  78.                 PrintRecord := THPrint(NewHandle(SizeOF(TPrint)));
  79.                 PrintDefault(PrintRecord);
  80.             end;
  81.         if PrError = NoErr then begin
  82.                 result := PrValidate(PrintRecord);
  83.                 result := PrStlDialog(PrintRecord);
  84.             end;
  85.         PrClose;
  86.     end;
  87.  
  88.  
  89.     procedure PrintHalftone;
  90.         const
  91.             PostScriptBegin = 190;
  92.             PostScriptEnd = 191;
  93.             PostScriptHandle = 192;
  94.             TextIsPostScript = 194;
  95.         var
  96.             HexBufH: handle;
  97.             hloc, vloc, HexCount, iheight, iwidth, hstart, vstart: integer;
  98.             Height, Width, eofStr, angle, freq: str255;
  99.             aLine: LineType;
  100.             HexBuf: packed array[0..4200] of char;
  101.             err: OSErr;
  102.             table: LookupTable;
  103.  
  104.         procedure PutHEX (byt: integer);
  105.             var
  106.                 i, LowByte, HighByte, tmp: integer;
  107.                 h: char;
  108.         begin
  109.             if not info^.IdentityFunction then
  110.                 byt := table[byt];
  111.             byt := 255 - byt;
  112.             LowByte := byt mod 16;
  113.             byt := byt div 16;
  114.             HighByte := byt mod 16;
  115.             for i := 1 to 2 do begin
  116.                     if i = 1 then
  117.                         tmp := HighByte
  118.                     else
  119.                         tmp := LowByte;
  120.                     case tmp of
  121.                         0: 
  122.                             h := '0';
  123.                         1: 
  124.                             h := '1';
  125.                         2: 
  126.                             h := '2';
  127.                         3: 
  128.                             h := '3';
  129.                         4: 
  130.                             h := '4';
  131.                         5: 
  132.                             h := '5';
  133.                         6: 
  134.                             h := '6';
  135.                         7: 
  136.                             h := '7';
  137.                         8: 
  138.                             h := '8';
  139.                         9: 
  140.                             h := '9';
  141.                         10: 
  142.                             h := 'a';
  143.                         11: 
  144.                             h := 'b';
  145.                         12: 
  146.                             h := 'c';
  147.                         13: 
  148.                             h := 'd';
  149.                         14: 
  150.                             h := 'e';
  151.                         15: 
  152.                             h := 'f';
  153.                     end;
  154.                     hexbuf[HexCount] := h;
  155.                     HexCount := HexCount + 1;
  156.                     if HexCount mod 80 = 0 then begin
  157.                             HexBuf[HexCount] := cr;
  158.                             HexCount := HexCount + 1
  159.                         end;
  160.                 end;
  161.         end;
  162.  
  163.     begin
  164.         with info^ do begin
  165.                 if not IdentityFunction then
  166.                     GetLookupTable(table);
  167.                 MoveTo(-1, -1);
  168.                 LineTo(-1, -1); {Nothing prints without this dummy dot!}
  169.                 PicComment(PostScriptBegin, 0, nil); {See Tech Note #91}
  170.                 PicComment(TextIsPostScript, 0, nil);
  171.                 NumToString(HalftoneFrequency, freq);
  172.                 NumToString(HalftoneAngle, angle);
  173.                 if HalftoneDotFunction then
  174.                     DrawString(concat(freq, ' ', angle, ' {dup mul exch dup mul add 1 exch sub} setscreen'))
  175.                 else
  176.                     DrawString(concat(freq, ' ', angle, ' {pop} setscreen'));
  177.                 DrawString('0 0 translate');
  178.                 with RoiRect do begin
  179.                         iwidth := right - left;
  180.                         if iwidth > MaxLine then
  181.                             iwidth := MaxLine;
  182.                         iheight := bottom - top;
  183.                         hstart := left;
  184.                         vstart := top;
  185.                     end;
  186.                 NumToString(iwidth, width);
  187.                 NumToString(iheight, height);
  188.                 DrawString(concat(width, ' ', height, ' scale'));
  189.                 DrawString(concat('/PicStr ', width, ' string def'));
  190.                 DrawString(concat(width, ' ', height, ' 8 [', width, ' 0 0 ', height, ' 0 0]'));
  191.                 DrawString('{currentfile PicStr readhexstring pop} image');
  192.                 for vloc := vstart to vstart + iheight - 1 do begin
  193.                         GetLine(hstart, vloc, iwidth, aline);
  194.                         HexCount := 0;
  195.                         for hloc := 0 to iwidth - 1 do
  196.                             PutHex(aline[hloc]);
  197.                         HexBuf[HexCount] := cr;
  198.                         HexCount := HexCount + 1;
  199.                         err := PtrToHand(@HexBuf, HexBufH, HexCount);
  200.                         if err <> noErr then
  201.                             exit(PrintHalftone);
  202.                         PicComment(PostScriptHandle, HexCount, HexBufH);
  203.                         DisposeHandle(HexBufH);
  204.                         Show2Values(vloc - vstart, iheight);
  205.                         if CommandPeriod then begin
  206.                                 beep;
  207.                                 eofStr := chr(4);
  208.                                 DrawString(eofStr);
  209.                                 exit(PrintHalftone)
  210.                             end;
  211.                     end;
  212.             end;
  213.     end;
  214.  
  215.  
  216.     procedure PrintTheImage (PageWidth, PageHeight: integer);
  217.         var
  218.             PrintRect: rect;
  219.             Width, Height: integer;
  220.  
  221.         procedure ScaleToFitPage;
  222.             var
  223.                 hscale, vscale, scale: extended;
  224.         begin
  225.             hscale := PageWidth / width;
  226.             vscale := PageHeight / height;
  227.             if hscale <= vscale then
  228.                 scale := hscale
  229.             else
  230.                 scale := vscale;
  231.             width := trunc(scale * width);
  232.             height := trunc(scale * height);
  233.         end;
  234.  
  235.         procedure CenterOnPage;
  236.         begin
  237.             with PrintRect do begin
  238.                     left := 0;
  239.                     top := 0;
  240.                     if width < PageWidth then
  241.                         left := (PageWidth - width) div 2;
  242.                     if height < PageHeight then
  243.                         top := (Pageheight - height) div 2;
  244.                     right := left + width;
  245.                     bottom := top + height;
  246.                 end;
  247.         end;
  248.  
  249.     begin
  250.         if isLaserWriter and (not DriverHalftoning) then
  251.             PrintHalftone
  252.         else
  253.             with info^ do begin
  254.                     LoadLUT(cTable);
  255.                     hlock(handle(osPort^.portPixMap));
  256.                     with RoiRect do begin
  257.                             width := right - left;
  258.                             height := bottom - top;
  259.                         end;
  260.                     if (width > PageWidth) or (height > PageHeight) then
  261.                         ScaleToFitPage;
  262.                     CenterOnPage;
  263.                     if BitAnd(qd.thePort^.portBits.rowBytes, $8000) = $8000 then begin
  264.                {Assume driver understands Color QD}
  265.                             CopyBits(BitMapHandle(osPort^.portPixMap)^^, BitMapHandle(CGrafPtr(qd.thePort)^.PortPixMap)^^, RoiRect, PrintRect, SrcCopy, nil);
  266.                         end
  267.                     else
  268.                         CopyBits(BitMapHandle(osPort^.portPixMap)^^, qd.thePort^.PortBits, RoiRect, PrintRect, SrcCopy, nil);
  269.                 end;
  270.     end;
  271.  
  272.  
  273.     procedure PrintTextBuffer (PageHeight: integer; var PrintPort: TPPrPort);
  274.         const
  275.             LineInc = 13;
  276.         var
  277.             vloc, i, LineCount, CharCount, LinesPerPage, MaxCount: integer;
  278.             aLine: str255;
  279.     begin
  280.         ClipTextInBuffer := false;
  281.         LinesPerPage := PageHeight div LineInc;
  282.         vloc := LineInc;
  283.         LineCount := 0;
  284.         CharCount := 0;
  285.         TextFont(Monaco);
  286.         TextSize(9);
  287.         if WhatToPrint = PrintText then
  288.             MaxCount := 85
  289.         else
  290.             MaxCount := 255;
  291.         i := 1;
  292.         repeat
  293.             CharCount := 0;
  294.             while (TextBufP^[i] <> cr) and (CharCount < MaxCount) and (i <= TextBufSize) do begin
  295.                     CharCount := CharCount + 1;
  296.                     aLine[CharCount] := TextBufP^[i];
  297.                     i := i + 1;
  298.                 end;
  299.             if TextBufP^[i] = cr then
  300.                 i := i + 1
  301.             else if CharCount = MaxCount then begin
  302.                     while (aLine[CharCount] <> ' ') and (CharCount > (MaxCount - 15)) do begin
  303.                             CharCount := CharCount - 1;
  304.                             i := i - 1;
  305.                         end;
  306.                     if TextBufP^[i] = ' ' then
  307.                         i := i + 1;
  308.                 end;
  309.             aLine[0] := chr(CharCount);
  310.             MoveTo(0, vloc);
  311.             DrawString(aLine);
  312.             vLoc := vLoc + LineInc;
  313.             LineCount := LineCount + 1;
  314.             if LineCount >= LinesPerPage then begin
  315.                     LineCount := 0;
  316.                     if i < TextBufSize then begin
  317.                             PrClosePage(PrintPort);
  318.                             PrintErrCheck;
  319.                             PrOpenPage(PrintPort, nil);
  320.                             vloc := LineInc
  321.                         end;
  322.                 end;
  323.         until i > TextBufSize;
  324.     end;
  325.  
  326.  
  327.     procedure DoPrintText (PageHeight: integer; var PrintPort: TPPrPort);
  328.         var
  329.             ByteCount: LongInt;
  330.     begin
  331.         if TextInfo <> nil then
  332.             with TextInfo^.TextTE^^ do begin
  333.                     ByteCount := TELength;
  334.                     BlockMove(hText^, ptr(TextBufP), ByteCount);
  335.                     TextBufSize := ByteCount;
  336.                     PrintTextBuffer(PageHeight, PrintPort);
  337.                 end;
  338.     end;
  339.  
  340.  
  341.     procedure Print (ShowDialog: boolean);
  342.         var
  343.             err, i, LinesToPrint: Integer;
  344.             tPort: GrafPtr;
  345.             PrintPort: TPPrPort;
  346.             PrintStatusRec: TPrStatus;
  347.             prect: rect;
  348.             result: boolean;
  349.     begin
  350.         if WhatToPrint = PrintImage then
  351.             SelectAll(false);
  352.         if (WhatToPrint = PrintImage) or (WhatToPrint = PrintSelection) then begin
  353.                 if OpPending then
  354.                     KillRoi;
  355.                 with info^.RoiRect do
  356.                     LinesToPrint := bottom - top;
  357.                 if not DriverHalftoning then begin
  358.                         DrawLabels('Line:', 'Total:', '');
  359.                         Show2Values(0, LinesToPrint);
  360.                     end;
  361.             end;
  362.         GetPort(tPort);
  363.         PrOpen;
  364.         if PrintRecord = nil then begin
  365.                 PrintRecord := THPrint(NewHandle(SizeOF(TPrint)));
  366.                 PrintDefault(PrintRecord);
  367.             end;
  368.         if PrError = NoErr then begin
  369.                 InitCursor;
  370.                 result := PrValidate(PrintRecord);
  371.                 isLaserWriter := BSR(PrintRecord^^.prStl.wDev, 8) = 3;
  372.                 prect := PrintRecord^^.prInfo.rPage;
  373.                 if ShowDialog then
  374.                     result := PrJobDialog(PrintRecord)
  375.                 else
  376.                     result := true;
  377.                 if not DriverHalftoning then
  378.                     ShowMessage(CmdPeriodToStop);
  379.                 ShowWatch;
  380.                 if result then
  381.                     for i := 1 to PrintRecord^^.PrJob.icopies do begin
  382.                             PrintPort := PrOpenDoc(PrintRecord, nil, nil);
  383.                             PrintErrCheck;
  384.                             Printing := true;
  385.                             PrOpenPage(PrintPort, nil);
  386.                             if PrError = NoErr then
  387.                                 case WhatToPrint of
  388.                                     PrintImage, PrintSelection: 
  389.                                         PrintTheImage(prect.right, prect.bottom);
  390.                                     PrintMeasurements:  begin
  391.                                             CopyResultsToBuffer(1, mCount, true);
  392.                                             PrintTextBuffer(prect.Bottom, PrintPort);
  393.                                             UnsavedResults := false;
  394.                                         end;
  395.                                     PrintPlot: 
  396.                                         DrawPlot;
  397.                                     PrintHistogram: 
  398.                                         DrawHistogram;
  399.                                     PrintText: 
  400.                                         DoPrintText(prect.Bottom, PrintPort);
  401.                                 end;
  402.                             Printing := false;
  403.                             PrClosePage(PrintPort);
  404.                             PrintErrCheck;
  405.                             PrCloseDoc(PrintPort);
  406.                             PrintErrCheck;
  407.                             if PrintRecord^^.prJob.bJDocLoop = bSpoolLoop then
  408.                                 PrPicFile(PrintRecord, nil, nil, nil, PrintStatusRec);
  409.                         end;
  410.             end;
  411.         PrClose;
  412.         SetPort(tPort);
  413.         if WhatToPrint = PrintImage then
  414.             KillRoi;
  415.         ShowMessage(' ');
  416.     end;
  417.  
  418.  
  419.     procedure SetHalftone;
  420.         const
  421.             FrequencyID = 8;
  422.             AngleID = 10;
  423.             DotID = 4;
  424.             LineID = 5;
  425.             CustomID = 13;
  426.         var
  427.             mylog: DialogPtr;
  428.             item, i, ignore, SaveFrequency, SaveAngle: integer;
  429.             SaveFunction, SaveCustom: boolean;
  430.             str: str255;
  431.     begin
  432.         SaveFrequency := HalftoneFrequency;
  433.         SaveAngle := HalftoneAngle;
  434.         SaveFunction := HalftoneDotFunction;
  435.         SaveCustom := DriverHalftoning;
  436.         mylog := GetNewDialog(30, nil, pointer(-1));
  437.         SetDNum(MyLog, FrequencyID, HalftoneFrequency);
  438.         SelectdialogItemText(MyLog, FrequencyID, 0, 32767);
  439.         SetDNum(MyLog, AngleID, HalftoneAngle);
  440.         SetDlogItem(mylog, CustomID, ord(not DriverHalftoning));
  441.         OutlineButton(MyLog, ok, 16);
  442.         if HalftoneDotFunction then
  443.             SetDlogItem(mylog, DotID, 1)
  444.         else
  445.             SetDlogItem(mylog, LineID, 1);
  446.         repeat
  447.             ModalDialog(nil, item);
  448.             if item = FrequencyID then begin
  449.                     HalftoneFrequency := GetDNum(MyLog, FrequencyID);
  450.                     DriverHalftoning := false;
  451.                     SetDlogItem(mylog, CustomID, ord(not DriverHalftoning));
  452.                 end;
  453.             if item = AngleID then begin
  454.                     HalftoneAngle := GetDNum(MyLog, AngleID);
  455.                     if (HalftoneAngle < 0) or (HalftoneAngle > 180) then begin
  456.                             beep;
  457.                             HalftoneAngle := SaveAngle;
  458.                         end;
  459.                     DriverHalftoning := false;
  460.                     SetDlogItem(mylog, CustomID, ord(not DriverHalftoning));
  461.                 end;
  462.             if (item >= DotID) and (item <= LineID) then begin
  463.                     for i := DotID to LineID do
  464.                         SetDlogItem(mylog, i, 0);
  465.                     SetDlogItem(mylog, item, 1);
  466.                     HalftoneDotFunction := item = DotID;
  467.                     DriverHalftoning := false;
  468.                     SetDlogItem(mylog, CustomID, ord(not DriverHalftoning));
  469.                 end;
  470.             if item = CustomID then begin
  471.                     DriverHalftoning := not DriverHalftoning;
  472.                     SetDlogItem(mylog, CustomID, ord(not DriverHalftoning));
  473.                 end;
  474.         until (item = ok) or (item = cancel);
  475.         DisposeDialog(mylog);
  476.         if item = cancel then begin
  477.                 HalftoneFrequency := SaveFrequency;
  478.                 HalftoneAngle := SaveAngle;
  479.                 HalftoneDotFunction := SaveFunction;
  480.                 DriverHalftoning := SaveCustom;
  481.             end;
  482.     end;
  483.  
  484.  
  485. {$POP}
  486.  
  487.     procedure GetFileInfo (name: str255; vnum: integer; var DateCreated, LastModified: str255);
  488.         var
  489.             FileParmBlock: CInfoPBRec;
  490.             theErr: OSErr;
  491.             DateVar, TimeVar: str255;
  492.             Secs: LongInt;
  493.     begin
  494.         DateCreated := '';
  495.             with FileParmBlock do begin
  496.                     ioCompletion := nil;
  497.                     ioNamePtr := @name;
  498.                     ioVRefNum := vnum;
  499.                     ioFVersNum := 0;
  500.                     ioFDirIndex := 0;
  501.                     theErr := PBGetCatInfoSync(@FileParmBlock); {ppc-bug}
  502.                     if theErr = NoErr then begin
  503.                             Secs := ioFlCrDat;
  504.                             IUDateString(Secs, abbrevDate, DateVar);
  505.                             IUTimeString(Secs, true, TimeVar);
  506.                             DateCreated := concat(DateVar, '  ', TimeVar);
  507.                             Secs := ioFlMDDat;
  508.                             IUDateString(Secs, abbrevDate, DateVar);
  509.                             IUTimeString(Secs, true, TimeVar);
  510.                             LastModified := concat(DateVar, '  ', TimeVar);
  511.                         end;
  512.                 end;
  513.     end;
  514.  
  515.  
  516.     procedure GetVolumnInfo (vnum: integer; var VolumnName: str255; var FreeSpace: LongInt);
  517.         var
  518.             theErr: OSErr;
  519.             str: str255;
  520.             VolParmBlock: ParamBlockRec;
  521.     begin
  522.         VolumnName := '';
  523.             with VolParmBlock do begin
  524.                     str := '';
  525.                     ioVRefNum := vnum;
  526.                     ioNamePtr := @str;
  527.                     ioCompletion := nil;
  528.                     ioVolIndex := -1;
  529.                     theErr := PBGetVInfoSync(@VolParmBlock); {ppc-bug}
  530.                     VolumnName := ioNamePtr^;
  531.                     FreeSpace := ioVAlBlkSiz * ioVFrBlk;
  532.                 end;
  533.     end;
  534.  
  535.  
  536.     function RoomForFile (fname: str255; RefNum: integer; slines, sPixelsPerLine: integer; SavingSelection: boolean): boolean;
  537.         var
  538.             err: OSErr;
  539.             f: integer;
  540.             VolumnName: str255;
  541.             FreeSpace, ExistingFileSize, NeededSize: LongInt;
  542.     begin
  543.         with info^ do begin
  544.                 ExistingFileSize := 0;
  545.                 RoomForFile := true;
  546.                 err := fsopen(fname, RefNum, f);
  547.                 if err = 0 then begin
  548.                         err := GetEOF(f, ExistingFileSize);
  549.                         err := fsClose(f);
  550.                     end;
  551.                 if ExistingFileSize <> 0 then begin
  552.                         if SavingSelection then begin
  553.                                 NeededSize := sLines;
  554.                                 NeededSize := NeededSize * sPixelsPerLine
  555.                             end
  556.                         else
  557.                             NeededSize := ImageSize;
  558.                         if StackInfo <> nil then
  559.                             with StackInfo^ do
  560.                                 NeededSize := NeededSize * nSlices + nSlices * SizeOf(StackIFDType);
  561.                         GetVolumnInfo(RefNum, VolumnName, FreeSpace);
  562.                         if (NeededSize - ExistingFileSize + 8192) > FreeSpace then begin
  563.                                 PutError('There is not enough free space on this disk to save this image.');
  564.                                 RoomForFile := false;
  565.                             end;
  566.                     end;
  567.             end;
  568.     end;
  569.  
  570.  
  571.     procedure GetInfo;
  572.         var
  573.             name, str, DateCreated, LastModified, VolumnName, str2: str255;
  574.             hloc, vloc, InfoWidth, InfoHeight: integer;
  575.             SaveRoiShowing: boolean;
  576.             FreeSpace, DataSize: LongInt;
  577.             SaveForeIndex, SaveBackIndex: integer;
  578.             ImageInfo, InfoWindowInfo: InfoPtr;
  579.             x1, y1, x2, y2, ulength, clength: extended;
  580.             SaveGDevice: GDHandle;
  581.  
  582.         procedure NewLine;
  583.         begin
  584.             vloc := vloc + 13;
  585.             MoveTo(hloc, vloc);
  586.         end;
  587.  
  588.         procedure NewParagraph;
  589.         begin
  590.             vloc := vloc + 18;
  591.             MoveTo(hloc, vloc);
  592.         end;
  593.  
  594.     begin
  595.         InfoWidth := 260;
  596.         InfoHeight := 260;
  597.         with info^ do begin
  598.                 if RoiShowing then
  599.                     InfoHeight := InfoHeight + 50;
  600.                 if RoiShowing and (RoiType = LineRoi) then
  601.                     InfoHeight := InfoHeight + 20;
  602.                 if vref <> 0 then
  603.                     InfoHeight := InfoHeight + 60;
  604.                 name := concat('Info About ', title);
  605.                 SaveRoiShowing := RoiShowing;
  606.             end;
  607.         SaveForeIndex := ForegroundIndex;
  608.         SaveBackIndex := BackgroundIndex;
  609.         SetForegroundColor(BlackIndex);
  610.         SetBackgroundColor(WhiteIndex);
  611.         ImageInfo := info;
  612.         if NewPicWindow(name, InfoWidth, InfoHeight) then
  613.             with ImageInfo^ do begin
  614.                     InfoWindowInfo := Info;
  615.                     SaveGDevice := GetGDevice;
  616.                     SetGDevice(osGDevice);
  617.                     SetPort(GrafPtr(info^.osPort));
  618.                     TextFont(Geneva);
  619.                     TextSize(9);
  620.                     hloc := 15;
  621.                     vloc := 10;
  622.                     NewLine;
  623.                     DrawBString('Name: ');
  624.                     DrawString(title);
  625.                     NewParagraph;
  626.                     DrawBString('Width: ');
  627.                     DrawXDimension(PixelsPerLine, 0);
  628.                     NewLine;
  629.                     DrawBString('Height: ');
  630.                     DrawYDimension(nlines, 0);
  631.                     if StackInfo <> nil then begin
  632.                             NewLine;
  633.                             DrawBString('Depth: ');
  634.                             DrawLong(StackInfo^.nSlices);
  635.                         end;
  636.                     NewLine;
  637.                     DrawBString('Size: ');
  638.                     if StackInfo <> nil then
  639.                         DataSize := PixMapSize * StackInfo^.nSlices
  640.                     else if DataH <> nil then
  641.                         DataSize := PixMapSize + PixMapSize * SizeOf(real)
  642.                     else
  643.                         DataSize := PixMapSize;
  644.                     DrawLong((DataSize + 511) div 1024);
  645.                     DrawString('K');
  646.                     NewParagraph;
  647.                     GetFileInfo(title, vref, DateCreated, LastModified); {DateCreated:='';}
  648.                     if DateCreated <> '' then begin
  649.                             DrawBString('Creation Date: ');
  650.                             DrawString(DateCreated);
  651.                             NewLine;
  652.                             DrawBString('Last Modified: ');
  653.                             DrawString(LastModified);
  654.                             NewLine;
  655.                         end;
  656.                     if fileVersion > 0 then begin
  657.                             DrawBString('Version: ');
  658.                             DrawString('Created by NIH Image ');
  659.                             DrawReal(fileVersion / 100.0, 1, 2);
  660.                             NewParagraph;
  661.                         end;
  662.                     DrawBString('Type: ');
  663.                     if StackInfo <> nil then case StackInfo^.StackType of
  664.                         VolumeStack, MovieStack:
  665.                             str := concat('Stack (', long2str(StackInfo^.nSlices), '  slices)');
  666.                         rgbStack:
  667.                             str := 'RGB color stack';
  668.                         else
  669.                         ;
  670.                     end else begin
  671.                             case PictureType of
  672.                                 NewPicture: 
  673.                                     str := 'New';
  674.                                 Normal: 
  675.                                     str := 'Normal';
  676.                                 PictFile: 
  677.                                     str := 'PICT';
  678.                                 TiffFile: 
  679.                                     str := 'TIFF';
  680.                                 Leftover: 
  681.                                     str := 'Left Over';
  682.                                 Imported:  begin
  683.                                         if DataType = EightBits then
  684.                                             str := 'Imported 8-bit image'
  685.                                         else
  686.                                             str := 'Imported 16-bit image';
  687.                                     end;
  688.                                 FrameGrabberType: 
  689.                                     str := 'Camera';
  690.                                 BlankField: 
  691.                                     str := 'Blank Field';
  692.                                 otherwise
  693.                                     ;
  694.                             end;
  695.                             if BinaryPic then
  696.                                 str := concat(str, ' (Binary)');
  697.                         end;
  698.                     DrawString(str);
  699.                     if StackInfo <> nil then
  700.                         with StackInfo^ do
  701.                             if SliceSpacing <> 0.0 then begin
  702.                                     NewLine;
  703.                                     DrawBString('Slice Spacing: ');
  704.                                     if SpatiallyCalibrated then
  705.                                         DrawString(StringOf(SliceSpacing / xScale:1:2, ' ', xunit, ' (', SliceSpacing:1:2, ' pixels)'))
  706.                                     else
  707.                                         DrawString(StringOf(SliceSpacing:1:2, ' pixels'));
  708.                                 end;
  709.                     NewLine;
  710.                     DrawBString('Lookup Table: ');
  711.                     case LutMode of
  712.                         PseudoColor: 
  713.                             str := concat('Pseudocolor (', long2str(ncolors), ', ', long2str(ColorStart), '-', long2str(ColorEnd), ')');
  714.                         GrayScale: 
  715.                             str := concat('Grayscale (', long2str(ncolors), ', ', long2str(ColorStart), '-', long2str(ColorEnd), ')');
  716.                         ColorLut: 
  717.                             str := 'Color';
  718.                         CustomGrayscale: 
  719.                             str := 'Custom Grayscale';
  720.                         otherwise
  721.                     end;
  722.                     DrawString(str);
  723.                     NewLine;
  724.                     DrawBString('Magnification: ');
  725.                     if ScaleToFitWindow then begin
  726.                             DrawReal(magnification, 1, 2);
  727.                             DrawString(' (Scale to Window Mode)')
  728.                         end
  729.                     else begin
  730.                             DrawReal(magnification, 1, 0);
  731.                             DrawString(':1')
  732.                         end;
  733.                     NewLine;
  734.                     DrawBString('Scale: ');
  735.                     if SpatiallyCalibrated then begin
  736.                             DrawReal(xScale, 1, 3);
  737.                             DrawString(' pixels per ');
  738.                             DrawString(xUnit);
  739.                             if PixelAspectRatio <> 1.0 then begin
  740.                                     NewLine;
  741.                                     DrawBString('Pixel Aspect Ratio: ');
  742.                                     DrawReal(PixelAspectRatio, 1, 4);
  743.                                 end;
  744.                         end
  745.                     else
  746.                         DrawString('None');
  747.                     if fit <> uncalibrated then begin
  748.                             NewLine;
  749.                             DrawBString('Unit of Measure: ');
  750.                             if UnitOfMEasure = '' then
  751.                                 DrawString('None')
  752.                             else
  753.                                 DrawString(UnitOfMeasure)
  754.                         end;
  755.                     NewParagraph;
  756.                     DrawBString('Free RAM: ');
  757.                     DrawLong(FreeMem div 1024);
  758.                     DrawString('K');
  759.                     NewLine;
  760.                     DrawBString('Largest Free Block: ');
  761.                     DrawLong(MaxBlock div 1024);
  762.                     DrawString('K');
  763.                     if FrameGrabber <> NoFrameGrabber then begin
  764.                             NewLine;
  765.                             DrawBString('Frame Grabber: ');
  766.                             case FrameGrabber of
  767.                                 QuickCapture:  begin
  768.                                         if fgWidth = 768 then
  769.                                             DrawString('50Hz')
  770.                                         else
  771.                                             DrawString('60Hz');
  772.                                         DrawString(' Data Translation QuickCapture');
  773.                                     end;
  774.                                 ScionLG3:  begin
  775.                                         if fgWidth = 768 then
  776.                                             DrawString('50Hz')
  777.                                         else
  778.                                             DrawString('60Hz');
  779.                                         DrawString(' Scion LG-3 (');
  780.                                         DrawLong(MaxLG3Frames div 2);
  781.                                         DrawString(' MB)');
  782.                                     end;
  783.                                 ScionAG5:  begin
  784.                                     if fgWidth = 768 then
  785.                                         DrawString('50Hz')
  786.                                     else
  787.                                         DrawString('60Hz');
  788.                                     DrawString(' Scion AG-5');
  789.                                 end;
  790.                                 ScionVG5f:  begin
  791.                                     if fgWidth = 768 then
  792.                                         DrawString('50Hz')
  793.                                     else
  794.                                         DrawString('60Hz');
  795.                                     DrawString(' Scion VG-5');
  796.                                 end
  797.                                 QTvdig:
  798.                                     DrawString('QuickTime Video Digitizer');
  799.                             end;
  800.                         end;
  801.                     NewParagraph;
  802.                     if RoiType <> NoRoi then begin
  803.                             DrawBString('Selection Type: ');
  804.                             case RoiType of
  805.                                 PolygonRoi: 
  806.                                     DrawString('Polygon');
  807.                                 FreehandRoi: 
  808.                                     DrawString('Freehand');
  809.                                 RectRoi: 
  810.                                     DrawString('Rectangle');
  811.                                 OvalRoi: 
  812.                                     DrawString('Oval');
  813.                                 LineRoi: 
  814.                                     DrawString('Straight Line');
  815.                                 FreeLineRoi: 
  816.                                     DrawString('Freehand Line');
  817.                                 SegLineRoi: 
  818.                                     DrawString('Segmented Line');
  819.                                 TracedRoi:
  820.                                     DrawString('Traced');
  821.                             end;
  822.                             NewLine;
  823.                             case RoiType of
  824.                                 PolygonRoi, FreehandRoi, RectRoi, OvalRoi, TracedRoi: 
  825.                                     with RoiRect do begin
  826.                                             DrawBString('    Left: ');
  827.                                             DrawXDimension(left, 0);
  828.                                             NewLine;
  829.                                             DrawBString('    Top: ');
  830.                                             if InvertYCoordinates then
  831.                                                 DrawYDimension(PicRect.bottom - top - 1, 0)
  832.                                             else
  833.                                                 DrawYDimension(top, 0);
  834.                                             NewLine;
  835.                                             DrawBString('    Width: ');
  836.                                             DrawXDimension(right - left, 0);
  837.                                             NewLine;
  838.                                             DrawBString('    Height: ');
  839.                                             DrawYDimension(bottom - top, 0);
  840.                                         end;
  841.                                 LineRoi:  begin
  842.                                         info := ImageInfo;
  843.                                         GetLengthOrPerimeter(ulength, clength);
  844.                                         GetLoi(x1, y1, x2, y2);
  845.                                         Info := InfoWindowInfo;
  846.                                         DrawBString('    Length: ');
  847.                                         if SpatiallyCalibrated then begin
  848.                                                 DrawReal(cLength, 1, 2);
  849.                                                 DrawString(xUnit);
  850.                                             end
  851.                                         else
  852.                                             DrawReal(uLength, 1, 2);
  853.                                         NewLine;
  854.                                         DrawBString('    Angle: ');
  855.                                         DrawReal(LAngle, 1, 2);
  856.                                         DrawString('°');
  857.                                         NewLine;
  858.                                         DrawBString('    X1: ');
  859.                                         DrawXDimension(x1, 2);
  860.                                         NewLine;
  861.                                         DrawBString('    Y1: ');
  862.                                         if InvertYCoordinates then
  863.                                             DrawYDimension(PicRect.bottom - y1 - 1, 2)
  864.                                         else
  865.                                             DrawYDimension(y1, 2);
  866.                                         NewLine;
  867.                                         DrawBString('    X2: ');
  868.                                         DrawXDimension(x2, 2);
  869.                                         NewLine;
  870.                                         DrawBString('    Y2: ');
  871.                                         if InvertYCoordinates then
  872.                                             DrawYDimension(PicRect.bottom - y2 - 1, 2)
  873.                                         else
  874.                                             DrawYDimension(y2, 2);
  875.                                     end;
  876.                                 FreeLineRoi, SegLineRoi:  begin
  877.                                         info := ImageInfo;
  878.                                         GetLengthOrPerimeter(ulength, clength);
  879.                                         Info := InfoWindowInfo;
  880.                                         DrawBString('    Length: ');
  881.                                         if SpatiallyCalibrated then begin
  882.                                                 DrawReal(cLength, 1, 2);
  883.                                                 DrawString(xUnit);
  884.                                             end
  885.                                         else
  886.                                             DrawReal(uLength, 1, 2);
  887.                                         NewLine;
  888.                                     end;
  889.                                 otherwise
  890.                             end; {case}
  891.                         end
  892.                     else
  893.                         DrawBString('No Selection');
  894.                     SetGDevice(SaveGDevice);
  895.                 end; {with ImageInfo^}
  896.         SetForegroundColor(SaveForeIndex);
  897.         SetBackgroundColor(SaveBackIndex);
  898.     end;
  899.  
  900.  
  901.     function CheckIO (err: OSerr): integer;
  902.         var
  903.             ErrStr, Message: str255;
  904.             ignore: integer;
  905.             SaveGDevice: GDHandle;
  906.     begin
  907.         if err <> 0 then begin
  908.                 case err of
  909.                     -34: Message := 'Disk Full';
  910.                     -35: Message := 'No such volume';
  911.                     -36: Message := 'I/O Error';
  912.                     -39: Message := 'End of file error';
  913.                     -49: Message := 'File in Use';
  914.                     -61: Message := 'Write Permission Error';
  915.                     -120: Message := 'Folder not found'
  916.                     otherwise Message := '';
  917.                 end;
  918.                 SaveGDevice := GetGDevice;
  919.                 SetGDevice(GetMainDevice);
  920.                 NumToString(err, ErrStr);
  921.                 ParamText(Message, ErrStr, '', '');
  922.                 InitCursor;
  923.                 ignore := alert(IOErrorID, nil);
  924.                 SetGDevice(SaveGDevice);
  925.                 AbortMacro;
  926.             end;
  927.         CheckIO := err;
  928.     end;
  929.     
  930.  
  931.  
  932.     function OpenMacPaint (fname: str255; vnum: integer): boolean;
  933.         const
  934.             MaxUnPackedSize = 51840;   {Max MacPaint size in bytes=720 lines * 72 bytes/line }
  935.         type
  936.             mpLine = array[1..18] of LongInt;
  937.             mpArrayT = array[1..720] of mpLine;
  938.             mpArrayP = ^mpArrayT;
  939.         var
  940.             i, f, ScanLine, LastLine, LastWord, LastColumn: integer;
  941.             err: osErr;
  942.             srcSize: LongInt;
  943.             srcPtr, dstPtr, src, dst: ptr;
  944.             theBitMap: BitMap;
  945.             mpArray: mpArrayP;
  946.             BlankLine, BlankColumn: boolean;
  947.             frect: rect;
  948.             SaveGDevice: GDHandle;
  949.  
  950.         procedure abort;
  951.         begin
  952.             beep;
  953.             if srcPtr <> nil then
  954.                 DisposePtr(srcPtr);
  955.             if dstPtr <> nil then
  956.                 DisposePtr(dstPtr);
  957.             {exit(OpenMacPaint);} {ppc-bug}
  958.         end;
  959.  
  960.     begin
  961.         OpenMacPaint := false;
  962.         err := fsOpen(fname, vnum, f);
  963.         if CheckIO(err) <> noErr then
  964.             exit(OpenMacPaint);
  965.         err := GetEOF(f, srcSize);
  966.         srcSize := srcSize - 512;
  967.         srcPtr := NewPtr(srcSize);
  968.         if srcPtr = nil then begin
  969.             abort;
  970.             exit(OpenMacPaint);
  971.         end;
  972.         err := SetFPos(f, fsFromStart, 512);
  973.         err := fsRead(f, srcSize, srcPtr);
  974.         if CheckIO(err) <> noErr then
  975.             exit(OpenMacPaint);
  976.         err := fsClose(f);
  977.         dstPtr := NewPtrClear(MaxUnPackedSize);
  978.         if dstPtr = nil then begin
  979.             abort;
  980.             exit(OpenMacPaint);
  981.         end;
  982.         src := srcPtr;
  983.         dst := dstPtr;
  984.         for scanLine := 1 to 720 do
  985.             UnPackBits(src, dst, 72); {bumps both ptrs}
  986.         DisposePtr(srcPtr);
  987.         mpArray := mpArrayP(dstPtr);
  988.         LastLine := 720;
  989.         BlankLine := true;
  990.         repeat
  991.             for i := 1 to 18 do
  992.                 blankLine := BlankLine and (mpArray^[LastLine, i] = 0);
  993.             if BlankLine then
  994.                 LastLine := LastLine - 1;
  995.         until (not BlankLine) or (LastLine = 1);
  996.         LastWord := 18;
  997.         BlankColumn := true;
  998.         repeat
  999.             for i := 1 to LastLine do
  1000.                 blankColumn := BlankColumn and (mpArray^[i, LastWord] = 0);
  1001.             if BlankColumn then
  1002.                 LastWord := LastWord - 1;
  1003.         until (not BlankColumn) or (LastWord = 1);
  1004.         LastColumn := LastWord * 32;
  1005.         LastColumn := LastColumn + 8;
  1006.         if LastColumn > 576 then
  1007.             LastColumn := 576;
  1008.         LastLine := LastLine + 8;
  1009.         if LastLine > 720 then
  1010.             LastLine := 720;
  1011.         SetRect(frect, 0, 0, LastColumn, LastLine);
  1012.         with theBitMap do begin
  1013.                 baseAddr := dstPtr;
  1014.                 rowBytes := 72;
  1015.                 bounds := frect;
  1016.             end;
  1017.         if not NewPicWindow(fname, LastColumn, LastLine) then begin
  1018.             abort;
  1019.             exit(OpenMacPaint);
  1020.         end;
  1021.         SaveGDevice := GetGDevice;
  1022.         SetGDevice(osGDevice);
  1023.         SetForegroundColor(BlackIndex);
  1024.         SetBackgroundColor(WhiteIndex);
  1025.         with info^ do begin
  1026.                 CopyBits(theBitMap, BitMapHandle(osPort^.PortPixMap)^^, frect, frect, SrcCopy, nil);
  1027.                 DisposePtr(dstPtr);
  1028.                 PictureType := imported;
  1029.                 BinaryPic := true;
  1030.                 SetGDevice(SaveGDevice);
  1031.                 if PixMapSize > UndoBufSize then
  1032.                     PutWarning;
  1033.             end;
  1034.         OpenMacPaint := true;
  1035.     end;
  1036.  
  1037.  
  1038.     procedure TypeMismatch (fname: str255);
  1039.     begin
  1040.         PutError(concat('The file "', fname, '" is a different type, and therefore cannot be replaced'));
  1041.     end;
  1042.  
  1043.  
  1044.  
  1045.     function GetTextFile (var name: str255; var RefNum: integer): boolean;
  1046.         var
  1047.             where: Point;
  1048.             typeList: SFTypeList;
  1049.             reply: SFReply;
  1050.             err: OSErr;
  1051.             pBlock: WDPBRec;
  1052.     begin
  1053.         where.v := 120;
  1054.         where.h := 120;
  1055.         typeList[0] := 'TEXT';
  1056.         SFGetFile(Where, '', nil, 1, @typeList, nil, reply);
  1057.         if reply.good then
  1058.             with reply do begin
  1059.                     name := fname;
  1060.                     RefNum := vRefNum;
  1061.                     GetTextFile := true;
  1062.                 end
  1063.         else
  1064.             GetTextFile := false;
  1065.     end;
  1066.  
  1067.  
  1068.     procedure GetBuffer;
  1069.         var
  1070.             err: OSErr;
  1071.             count, FilePos: LongInt;
  1072.     begin
  1073.         count := MaxTextBufSize;
  1074.         err := fsread(Textf, count, ptr(TextBufP));
  1075.         TextBufSize := count;
  1076.         err := GetFPos(Textf, FilePos);
  1077.         if FilePos = TextFileSize then begin
  1078.                 TextBufSize := TextBufSize + 1;
  1079.                 if TextBufSize > MaxTextBufSize then
  1080.                     TextBufSize := MaxTextBufSize;
  1081.                 TextBufP^[TextBufSize] := eofChr;
  1082.                 err := fsclose(Textf);
  1083.             end;
  1084.         TextIndex := 1;
  1085.     end;
  1086.  
  1087.  
  1088.     function GetByte: char;
  1089.     begin
  1090.         GetByte := TextBufP^[TextIndex];
  1091.         TextIndex := TextIndex + 1;
  1092.         if TextIndex > MaxTextBufSize then
  1093.             GetBuffer;
  1094.     end;
  1095.  
  1096.  
  1097.     function GetNumber: extended;
  1098.         var
  1099.             c: char;
  1100.             str: str255;
  1101.     begin
  1102.         repeat
  1103.             c := GetByte;
  1104.             if c = tab then begin
  1105.                     GetNumber := 0.0; {Assume 0 zero for missing value.}
  1106.                     exit(GetNumber);
  1107.                 end;
  1108.             if (c = cr) or (c = eofChr) then begin
  1109.                     TextEol := true;
  1110.                     TextEof := c = eofChr;
  1111.                     GetNumber := NoValue;
  1112.                     exit(GetNumber);
  1113.                 end;
  1114.         until c in ['0'..'9', '-', '.'];
  1115.         Str := '';
  1116.         while c in ['0'..'9', '+', '-', '.', 'e', 'E'] do begin
  1117.                 Str := concat(str, c);
  1118.                 c := GetByte;
  1119.                 if (c = cr) or (c = eofChr) then begin
  1120.                         TextEol := true;
  1121.                         TextEof := c = eofChr;
  1122.                     end;
  1123.             end;
  1124.         GetNumber := StringToReal(str);
  1125.     end;
  1126.  
  1127.  
  1128.     procedure GetLineFromText (var rLine: RealLine; var count: integer);
  1129.         var
  1130.             n: extended;
  1131.     begin
  1132.         count := 0;
  1133.         if TextEof then
  1134.             exit(GetLineFromText);
  1135.         repeat
  1136.             n := GetNumber;
  1137.             if n <> NoValue then begin
  1138.                     count := count + 1;
  1139.                     rLine[count] := n;
  1140.                 end;
  1141.         until TextEol or (count = MaxLine);
  1142.         TextEol := false;
  1143.     end;
  1144.  
  1145.  
  1146.     procedure InitTextInput (name: str255; RefNum: integer);
  1147.         var
  1148.             err: OSErr;
  1149.     begin
  1150.         err := FSOpen(name, RefNum, Textf);
  1151.         err := GetEof(Textf, TextFileSize);
  1152.         err := SetFPos(Textf, fsFromStart, 0);
  1153.         ShowWatch;
  1154.         if WhatsOnClip = TextOnClip then
  1155.             WhatsOnClip := NothingOnClip;
  1156.         GetBuffer;
  1157.         TextEol := false;
  1158.         TextEof := false;
  1159.     end;
  1160.  
  1161.  
  1162.     function ImportTextFile (name: str255; RefNum: integer): boolean;
  1163.         var
  1164.             nRows, nColumns, count, i, vloc, BlankPixel, nPixelsPerLine: integer;
  1165.             rLine: RealLine;
  1166.             pvalue: extended;
  1167.             min, max, ScaleFactor, DefaultValue, tvalue: extended;
  1168.             err: OSErr;
  1169.             line, BlankLine: LineType;
  1170.             TheInfo: FInfo;
  1171.             noScaling:boolean;
  1172.     begin
  1173.         ImportTextFile := false;
  1174.         err := GetFInfo(name, RefNum, TheInfo);
  1175.         if TheInfo.fdType <> 'TEXT' then begin
  1176.                 PutError('File is not of type ''TEXT''.');
  1177.                 exit(ImportTextFile);
  1178.             end;
  1179.         InitTextInput(name, RefNum);
  1180.         nRows := 0;
  1181.         nColumns := 0;
  1182.         max := -10e-10;
  1183.         min := 10e10;
  1184.         ShowMessage(concat('First pass used to find ', crStr, 'width, height,min, and max.', crStr, crStr, CmdPeriodToStop));
  1185.         DrawLabels('Line:', '', '');
  1186.         while not TextEof do begin
  1187.                 GetLineFromText(rLine, count);
  1188.                 if not (TextEof and (count = 0)) then
  1189.                     nRows := nRows + 1;
  1190.                 if count > nColumns then
  1191.                     nColumns := count;
  1192.                 for i := 1 to count do begin
  1193.                         pvalue := rLine[i];
  1194.                         if pvalue > max then
  1195.                             max := pvalue;
  1196.                         if pvalue < min then
  1197.                             min := pvalue;
  1198.                     end;
  1199.                 if nRows mod 10 = 0 then begin
  1200.                         Show1Value(nRows, NoValue);
  1201.                         ShowAnimatedWatch;
  1202.                         if CommandPeriod then begin
  1203.                                 beep;
  1204.                                 err := fsclose(Textf);
  1205.                                 Exit(ImportTextFile);
  1206.                             end;
  1207.                     end;
  1208.             end;
  1209.         ShowMessage(concat('rows= ', long2str(nRows), crStr, 'columns= ', long2str(ncolumns), crStr, 'min= ', long2str(round(min)), crStr, 'max= ', long2str(round(max))));
  1210.         if nColumns > MaxLine then begin
  1211.                 PutError(concat('More than ',long2str(MaxLine),' pixels per line.'));
  1212.                 Exit(ImportTextFile);
  1213.             end;
  1214.         nPixelsPerLine := nColumns;
  1215.         if NewPicWindow(name, nPixelsPerLine, nrows) then
  1216.             with info^ do begin
  1217.                     if (not ImportAutoScale) and (max > min) then begin
  1218.                             min := ImportMin;
  1219.                             max := ImportMax;
  1220.                         end;
  1221.                     ScaleFactor := 253.0 / (max - min);
  1222.                     InitTextInput(name, RefNum);
  1223.                     vloc := 0;
  1224.                     DefaultValue := 0.0;
  1225.                     if DefaultValue < min then
  1226.                         DefaultValue := min;
  1227.                     if DefaultValue > max then
  1228.                         DefaultValue := max;
  1229.                     BlankPixel := round((DefaultValue - min) * ScaleFactor + 1);
  1230.                     for i := 0 to nColumns - 1 do
  1231.                         BlankLine[i] := BlankPixel;
  1232.                     NoScaling:=not ImportAutoScale and ((min=0) and (max=255));
  1233.                     DrawLabels('Line:', 'Total:', '');
  1234.                     while not TextEof do begin
  1235.                             GetLineFromText(rLine, count);
  1236.                             if not (TextEof and (count = 0)) then begin
  1237.                                     line := BlankLine;
  1238.                                     if ImportAutoScale then     {Map values into the range 1-254}
  1239.                                         for i := 1 to count do
  1240.                                             line[i - 1] := round((rLine[i] - min) * ScaleFactor + 1)
  1241.                                     else
  1242.                                         for i := 1 to count do begin
  1243.                                                 tvalue := rLine[i];
  1244.                                                 if tvalue < min then
  1245.                                                     tvalue := min;
  1246.                                                 if tvalue > max then
  1247.                                                     tvalue := max;
  1248.                                                 if noScaling
  1249.                                                     then line[i - 1]:=round(tvalue)
  1250.                                                     else line[i - 1] := round((tvalue - min) * ScaleFactor + 1);
  1251.                                             end;
  1252.                                     PutLine(0, vloc, PixelsPerLine, line);
  1253.                                     vloc := vloc + 1;
  1254.                                 end;
  1255.                             if vloc mod 10 = 0 then begin
  1256.                                     Show2Values(vloc, nRows);
  1257.                                     ShowAnimatedWatch;
  1258.                                     if CommandPeriod then begin
  1259.                                             beep;
  1260.                                             err := fsclose(Textf);
  1261.                                             Exit(ImportTextFile);
  1262.                                         end;
  1263.                                 end;
  1264.                         end;
  1265.                     if noScaling then
  1266.                         ImportCalibrate:=false
  1267.                     else begin
  1268.                         fit := StraightLine;
  1269.                         nCoefficients := 2;
  1270.                         coefficient[2] := (max - min) / 253.0;
  1271.                         coefficient[1] := min - coefficient[2];
  1272.                         nKnownValues := 0;
  1273.                         UpdateTitleBar;
  1274.                         if macro then
  1275.                             GenerateValues;
  1276.                         ZeroClip := false;
  1277.                     end;
  1278.                     changes := true;
  1279.                     PictureType := imported;
  1280.                 end; {with}
  1281.         ImportTextFile := true;
  1282.     end;
  1283.  
  1284.  
  1285.     procedure PlotXYZ;
  1286. {Reads X-Y coordinate pairs and optional intensiy(Z) values from a}
  1287. {two or three column tab-delimited text file and plots them in the current window.}
  1288.         var
  1289.             fname, str: str255;
  1290.             RefNum, i, nColumns, nValues, index, wheight: integer;
  1291.             rLine: RealLine;
  1292.     begin
  1293.         RefNum := 0;
  1294.         if not GetTextFile(fname, RefNum) then
  1295.             exit(PlotXYZ);
  1296.         InitTextInput(fname, RefNum);
  1297.         GetLineFromText(rLine, nValues);
  1298.         nColumns := nValues;
  1299.         if not ((nColumns = 2) or (nColumns = 3)) then begin
  1300.                 PutError('File must have two or three columns.');
  1301.                 exit(PlotXYZ);
  1302.             end;
  1303.         wheight := info^.nLines;
  1304.         index := ForegroundIndex;
  1305.         repeat
  1306.             if nColumns = 3 then begin
  1307.                     index := round(rLine[3]);
  1308.                     if index > 255 then
  1309.                         index := 255;
  1310.                     if index < 0 then
  1311.                         index := 0;
  1312.                 end;
  1313.             PutPixel(round(rLine[1]), wheight - round(rLine[2] + 1), index);
  1314.             GetLineFromText(rLine, nValues);
  1315.         until nValues = 0;
  1316.         InitCursor;
  1317.     end;
  1318.  
  1319.  
  1320.  
  1321.     procedure SaveSettings;
  1322.         var
  1323.             TheInfo: FInfo;
  1324.             ByteCount: LongInt;
  1325.             f, i: integer;
  1326.             err: OSErr;
  1327.             settings: SettingsType;
  1328.             PrefsVRef: integer;
  1329.             PrefsDirID: LongInt;
  1330.             PrefsSpec: FSSpec;
  1331.             PrefsError:boolean;
  1332.     begin
  1333.         with settings, info^ do begin
  1334.                 sID := 'IMAG';
  1335.                 sVersion := version;
  1336.                 sForegroundIndex := ForegroundIndex;
  1337.                 sBackgroundIndex := BackgroundIndex;
  1338.                 sBrushHeight := BrushHeight;
  1339.                 sBrushWidth := BrushWidth;
  1340.                 sSprayCanDiameter := SprayCanDiameter;
  1341.                 sLUTMode := LUTMode;
  1342.                 sOldColorStart := 30;
  1343.                 sOldColorWidth := 10;
  1344.                 sCurrentFontID := CurrentFontID;
  1345.                 sCurrentStyle := CurrentStyle;
  1346.                 sCurrentSize := CurrentSize;
  1347.                 sTextJust := TextJust;
  1348.                 sTextBack := TextBack;
  1349.                 sNExtraColors := nExtraColors;
  1350.                 sExtraColors := ExtraColors;
  1351.                 sInvertVideo := InvertVideo;
  1352.                 sMeasurements := Measurements;
  1353.                 sInvertPlots := InvertPlots;
  1354.                 sAutoScalePlots := AutoScalePlots;
  1355.                 sLinePlot := LinePlot;
  1356.                 sDrawPlotLabels := DrawPlotLabels;
  1357.                 for i := 1 to 12 do
  1358.                     sUnused1[i] := 0;
  1359.                 sFixedSizePlot := FixedSizePlot;
  1360.                 sProfilePlotWidth := ProfilePlotWidth;
  1361.                 sProfilePlotHeight := ProfilePlotHeight;
  1362.                 sFramesToAverage := FramesToAverage;
  1363.                 sNewPicWidth := NewPicWidth;
  1364.                 sNewPicHeight := NewPicHeight;
  1365.                 sBufferSize := BufferSize;
  1366.                 sThresholdToForeground := ThresholdToForeground;
  1367.                 sNonThresholdToBackground := NonThresholdToBackground;
  1368.                 sVideoChannel := VideoChannel;
  1369.                 sWhatToImport := WhatToImport;
  1370.                 sImportCustomWidth := ImportCustomWidth;
  1371.                 sImportCustomHeight := ImportCustomHeight;
  1372.                 sImportCustomOffset := ImportCustomOffset;
  1373.                 sWandAutoMeasure := WandAutoMeasure;
  1374.                 sWandAdjustAreas := WandAdjustAreas;
  1375.                 sBinaryIterations := BinaryIterations;
  1376.                 sScaleArithmetic := ScaleArithmetic;
  1377.                 sInvertPixelValues := InvertPixelValues;
  1378.                 sInvertYCoordinates := InvertYCoordinates;
  1379.                 sFieldWidth := FieldWidth;
  1380.                 sPrecision := precision;
  1381.                 sMinParticleSize := MinParticleSize;
  1382.                 sMaxParticleSize := MaxParticleSize;
  1383.                 sIgnoreParticlesTouchingEdge := IgnoreParticlesTouchingEdge;
  1384.                 sLabelParticles := LabelParticles;
  1385.                 sOutlineParticles := OutlineParticles;
  1386.                 sIncludeHoles := IncludeHoles;
  1387.                 sOscillatingMovies := OscillatingMovies;
  1388.                 sDriverHalftoning := DriverHalftoning;
  1389.                 sMaxMeasurements := MaxMeasurements;
  1390.                 sImportCustomDepth := ImportCustomDepth;
  1391.                 sImportSwapBytes := ImportSwapBytes;
  1392.                 sImportCalibrate := ImportCalibrate;
  1393.                 sImportAutoscale := ImportAutoscale;
  1394.                 for i := 1 to 12 do
  1395.                     sUnused2[i] := 0;
  1396.                 sShowHeadings := ShowHeadings;
  1397.                 sDefaultVRefNum := 0;
  1398.                 sDefaultDirID := 0;
  1399.                 sKernelsVRefNum := 0;
  1400.                 sKernelsDirID := 0;
  1401.         {***}
  1402.                 sProfilePlotMin := ProfilePlotMin;
  1403.                 sProfilePlotMax := ProfilePlotMax;
  1404.                 sImportMin := ImportMin;
  1405.                 sImportMax := ImportMax;
  1406.                 sHighlightPixels := HighlightSaturatedPixels;
  1407.         {***}
  1408.                 sBallRadius := BallRadius;
  1409.                 sFasterBackgroundSubtraction := FasterBackgroundSubtraction;
  1410.                 sScaleConvolutions := ScaleConvolutions;
  1411.         {V1.42}
  1412.                 sBinaryCount := BinaryCount;
  1413.                 sColorTable := ColorTable;
  1414.                 sColorStart := ColorStart;
  1415.                 sColorEnd := ColorEnd;
  1416.                 sInvertedTable := InvertedColorTable;
  1417.         {V1.44}
  1418.                 sHalftoneFrequency := HalftoneFrequency;
  1419.                 sHalftoneAngle := HalftoneAngle;
  1420.                 sHalftoneDotFunction := HalftoneDotFunction;
  1421.                 sDacLow := DacLow;
  1422.                 sDacHigh := DacHigh;
  1423.                 sSyncMode := SyncMode;
  1424.                 sSwitchLUTOnSuspend := SwitchLUTOnSuspend;
  1425.                 sVideoRateAveraging := VideoRateAveraging;
  1426.                 sImportInvert := ImportInvert;
  1427.                 sTextCreator := TextCreator;
  1428.                 sMathSubGain:=MathSubGain;
  1429.                 sMathSubOffset:=round(MathSubOffset);
  1430.         {V1.60}
  1431.                 sfgScale := fgScale;
  1432.                 sUseBuiltinDigitizer := UseBuiltinDigitizer;
  1433.                 sDigitizerMode := DigitizerMode;
  1434.                 sDigitizerStandard := DigitizerStandard;
  1435.                 sLutFriendlyMode := LutFriendlyMode;
  1436.  
  1437.                 for i := 1 to 10 do
  1438.                     sUnused[i] := 0;
  1439.             end; {with}
  1440.         if System7 then begin
  1441.             {Save in Preferences folder}
  1442.             PrefsError:=true;
  1443.             err:=FindFolder(kOnSystemDisk, kPreferencesFolderType,
  1444.                         kDontCreateFolder, PrefsVRef, PrefsDirID);
  1445.             if err=noErr then
  1446.                 err:=FSMakeFSSpec(PrefsVRef, PrefsDirID, PrefsName, PrefsSpec);
  1447.             if err=noErr
  1448.                 then err:=FSpDelete(PrefsSpec);
  1449.             if (err=noErr) or (err=fnfErr) then begin
  1450.                 err:=FSpCreate(PrefsSpec, 'Imag', 'pref', smSystemScript);
  1451.                 if err=noErr then
  1452.                     err:=FSpOpenDF(PrefsSpec, fsCurPerm, f);
  1453.                 if err=noErr then
  1454.                     PrefsError:=false;
  1455.             end;
  1456.             if PrefsError then begin
  1457.                 PutError('Error saving settings file');
  1458.                 exit(SaveSettings);
  1459.             end;
  1460.         end else begin
  1461.             {Save in System folder}
  1462.             err := GetFInfo(PrefsName, SystemRefNum, TheInfo);
  1463.             if err = FNFerr then begin
  1464.                     err := create(PrefsName, SystemRefNum, 'Imag', 'pref');
  1465.                     if CheckIO(err) <> 0 then
  1466.                         exit(SaveSettings);
  1467.                 end;
  1468.             err := fsopen(PrefsName, SystemRefNum, f);
  1469.         end;
  1470.         if CheckIO(err) <> 0 then
  1471.             exit(SaveSettings);
  1472.         err := SetFPos(f, FSFromStart, 0);
  1473.         ByteCount := SizeOf(settings);
  1474.         err := fswrite(f, ByteCount, @settings);
  1475.         if CheckIO(err) <> 0 then begin
  1476.                 err := fsclose(f);
  1477.                 exit(SaveSettings)
  1478.             end;
  1479.         err := SetEof(f, ByteCount);
  1480.         err := fsclose(f);
  1481.         err := FlushVol(nil, SystemRefNum);
  1482.     end;
  1483.  
  1484.  
  1485.     procedure ExportAsText (fname: str255; RefNum: integer);
  1486.         var
  1487.             err, f, width, hloc, vloc: integer;
  1488.             TheInfo: FInfo;
  1489.             ByteCount, FileSize: LongInt;
  1490.             AutoSelectAll, InvertValues: boolean;
  1491.             tLine: LineType;
  1492.     begin
  1493.         if info = NoInfo then
  1494.             exit(ExportAsText);
  1495.         err := GetFInfo(fname, RefNum, TheInfo);
  1496.         case err of
  1497.             NoErr: 
  1498.                 if TheInfo.fdType <> 'TEXT' then begin
  1499.                         TypeMismatch(fname);
  1500.                         exit(ExportAsText)
  1501.                     end;
  1502.             FNFerr:  begin
  1503.                     err := create(fname, RefNum, FourCharCode(TextCreator), 'TEXT');
  1504.                     if CheckIO(err) <> 0 then
  1505.                         exit(ExportAsText);
  1506.                 end;
  1507.             otherwise
  1508.                 if CheckIO(err) <> 0 then
  1509.                     exit(ExportAsText)
  1510.         end;
  1511.         ShowWatch;
  1512.         err := fsopen(fname, RefNum, f);
  1513.         if CheckIO(err) <> 0 then
  1514.             exit(ExportAsText);
  1515.         AutoSelectAll := not info^.RoiShowing;
  1516.         if AutoSelectAll then
  1517.             SelectAll(true);
  1518.         if TooWide then
  1519.             exit(ExportAsText);
  1520.         FileSize := 0;
  1521.         with info^, info^.RoiRect do begin
  1522.                 InvertValues := isInvertingFunction;
  1523.                 width := right - left;
  1524.                 for vloc := top to bottom - 1 do begin
  1525.                         GetLine(left, vloc, width, tLine);
  1526.                         TextBufSize := 0;
  1527.                         for hloc := 0 to width - 1 do begin
  1528.                                 if fit = uncalibrated then
  1529.                                     PutLong(tLine[hloc], 0)
  1530.                                 else if InvertValues then
  1531.                                     PutLong(255 - tLine[hloc], 0)
  1532.                                 else
  1533.                                     PutString(StringOf(cValue[tLine[hloc]]:1:precision));
  1534.                                 if hloc <> (width - 1) then
  1535.                                     PutTab;
  1536.                             end;
  1537.                         PutChar(cr);
  1538.                         ByteCount := TextBufSize;
  1539.                         err := fswrite(f, ByteCount, ptr(TextBufP));
  1540.                         FIleSize := FileSize + ByteCount;
  1541.                         if (CheckIO(err) <> 0) or CommandPeriod then
  1542.                             leave;
  1543.                         if (vloc mod 10) = 0 then ShowAnimatedWatch;
  1544.                     end;
  1545.                 err := SetEof(f, FileSize);
  1546.                 err := fsclose(f);
  1547.                 err := FlushVol(nil, RefNum);
  1548.             end;
  1549.         if AutoSelectAll then
  1550.             KillRoi;
  1551.     end;
  1552.  
  1553.  
  1554.     procedure ExportCoordinates (fname: str255; RefNum: integer);
  1555.         var
  1556.             err, f, i, y: integer;
  1557.             TheInfo: FInfo;
  1558.             ByteCount, FileSize: LongInt;
  1559.             InvertY: boolean;
  1560.     begin
  1561.         if not CoordinatesAvailableMsg then begin
  1562.                 exit(ExportCoordinates)
  1563.             end;
  1564.         err := GetFInfo(fname, RefNum, TheInfo);
  1565.         case err of
  1566.             NoErr: 
  1567.                 if TheInfo.fdType <> 'TEXT' then begin
  1568.                         TypeMismatch(fname);
  1569.                         exit(ExportCoordinates)
  1570.                     end;
  1571.             FNFerr:  begin
  1572.                     err := create(fname, RefNum, FourCharCode(TextCreator), 'TEXT');
  1573.                     if CheckIO(err) <> 0 then
  1574.                         exit(ExportCoordinates);
  1575.                 end;
  1576.             otherwise
  1577.                 if CheckIO(err) <> 0 then
  1578.                     exit(ExportCoordinates)
  1579.         end;
  1580.         ShowWatch;
  1581.         err := fsopen(fname, RefNum, f);
  1582.         if CheckIO(err) <> 0 then
  1583.             exit(ExportCoordinates);
  1584.         FileSize := 0;
  1585.         InvertY := InvertYCoordinates and (Info <> NoInfo);
  1586.         with info^ do
  1587.             for i := 1 to nCoordinates do begin
  1588.                     TextBufSize := 0;
  1589.                     PutLong(xCoordinates^[i] + RoiRect.left, 0);
  1590.                     PutTab;
  1591.                     y := yCoordinates^[i] + RoiRect.top;
  1592.                     if InvertY then
  1593.                         y := PicRect.bottom - y - 1;
  1594.                     PutLong(y, 0);
  1595.                     PutChar(cr);
  1596.                     ByteCount := TextBufSize;
  1597.                     err := fswrite(f, ByteCount, ptr(TextBufP));
  1598.                     FIleSize := FileSize + ByteCount;
  1599.                     if (CheckIO(err) <> 0) or CommandPeriod then
  1600.                         leave;
  1601.                 end;
  1602.         err := SetEof(f, FileSize);
  1603.         err := fsclose(f);
  1604.         err := FlushVol(nil, RefNum);
  1605.     end;
  1606.  
  1607.  
  1608.     procedure ExportMeasurements (fname: str255; RefNum: integer);
  1609.         const
  1610.             LinesPerPass = 25;
  1611.         var
  1612.             err, f, i, first, last: integer;
  1613.             TheInfo: FInfo;
  1614.             ByteCount, FileSize: LongInt;
  1615.     begin
  1616.         err := GetFInfo(fname, RefNum, TheInfo);
  1617.         case err of
  1618.             NoErr: 
  1619.                 if TheInfo.fdType <> 'TEXT' then begin
  1620.                         TypeMismatch(fname);
  1621.                         exit(ExportMeasurements)
  1622.                     end;
  1623.             FNFerr:  begin
  1624.                     err := create(fname, RefNum, FourCharCode(TextCreator), 'TEXT');
  1625.                     if CheckIO(err) <> 0 then
  1626.                         exit(ExportMeasurements);
  1627.                 end;
  1628.             otherwise
  1629.                 if CheckIO(err) <> 0 then
  1630.                     exit(ExportMeasurements)
  1631.         end;
  1632.         ShowWatch;
  1633.         err := fsopen(fname, RefNum, f);
  1634.         if CheckIO(err) <> 0 then
  1635.             exit(ExportMeasurements);
  1636.         FileSize := 0;
  1637.         first := 1;
  1638.         last := LinesPerPass;
  1639.         repeat
  1640.             if last > mCount then
  1641.                 last := mCount;
  1642.             CopyResultsToBuffer(first, last, ShowHeadings or OptionKeyWasDown);
  1643.             ByteCount := TextBufSize;
  1644.             err := fswrite(f, ByteCount, ptr(TextBufP));
  1645.             FIleSize := FileSize + ByteCount;
  1646.             if (CheckIO(err) <> 0) or CommandPeriod or (last = mCount) then
  1647.                 leave;
  1648.             first := first + LinesPerPass;
  1649.             last := last + LinesPerPass;
  1650.         until false;
  1651.         err := SetEof(f, FileSize);
  1652.         err := fsclose(f);
  1653.         err := FlushVol(nil, RefNum);
  1654.         UnsavedResults := false;
  1655.     end;
  1656.  
  1657.  
  1658.  
  1659.     procedure Swap2Bytes (var i: integer);
  1660.         type
  1661.             atype = packed array[1..2] of char;
  1662.         var
  1663.             a: atype;
  1664.             c: char;
  1665.     begin
  1666.         a := atype(i);
  1667.         c := a[1];
  1668.         a[1] := a[2];
  1669.         a[2] := c;
  1670.         i := integer(a)
  1671.     end;
  1672.  
  1673.  
  1674.     procedure Swap4Bytes (var i: LongInt);
  1675.         var
  1676.             a: ostype;
  1677.             c: char;
  1678.     begin
  1679.         a := ostype(i);
  1680.         c := a[1];
  1681.         a[1] := a[4];
  1682.         a[4] := c;
  1683.         c := a[2];
  1684.         a[2] := a[3];
  1685.         a[3] := c;
  1686.         i := LongInt(a)
  1687.     end;
  1688.     
  1689.  
  1690.  
  1691.     function OpenTiffHeader (f: integer; var DirOffset: LongInt): boolean;
  1692.         var
  1693.             TiffHeader: TiffHdr;
  1694.             ByteCount: LongInt;
  1695.             err: OSErr;
  1696.     begin
  1697.         ByteCount := 8;
  1698.         err := SetFPos(f, fsFromStart, 0);
  1699.         err := fsread(f, ByteCount, @TiffHeader);
  1700.         if CheckIO(err) <> NoErr then begin
  1701.                 OpenTiffHeader := false;
  1702.                 exit(OpenTiffHeader);
  1703.             end;
  1704.         with TiffHeader do begin
  1705.                 IntelByteOrder := ByteOrder = 'II';
  1706.                 if (ByteOrder <> 'MM') and (ByteOrder <> 'II') then begin
  1707.                         PutError('Invalid TIFF header.');
  1708.                         OpenTiffHeader := false;
  1709.                         exit(OpenTiffHeader)
  1710.                     end;
  1711.                 DirOffset := FirstIFDOffset;
  1712.                 if IntelByteOrder then
  1713.                     Swap4Bytes(DirOffset);
  1714.                 OpenTiffHeader := true;
  1715.             end;
  1716.     end;
  1717.  
  1718.  
  1719.     procedure GetTiffEntry (f: integer; var tag: integer; var N, value: LongInt);
  1720.         var
  1721.             IFDEntry: TiffEntry;
  1722.             ByteCount: LongInt;
  1723.             IntValue: integer;
  1724.             err: OSErr;
  1725.             str: str255;
  1726.     begin
  1727.         ByteCount := 12;
  1728.         err := FSRead(f, ByteCount, @IFDEntry);
  1729.         with IFDEntry do begin
  1730.                 tag := TagField;
  1731.                 N := length;
  1732.                 if IntelByteOrder then begin
  1733.                         Swap2Bytes(tag);
  1734.                         Swap2Bytes(ftype);
  1735.                         Swap4Bytes(N);
  1736.                     end;
  1737.                 value := offset;
  1738.                 if (ftype = short) and (N = 1) then begin
  1739.                         value := bsr(value, 16);
  1740.                         if IntelByteOrder then begin
  1741.                                 IntValue := value;
  1742.                                 Swap2Bytes(IntValue);
  1743.                                 value := IntValue
  1744.                             end
  1745.                     end
  1746.                 else if IntelByteOrder then
  1747.                     Swap4Bytes(value);
  1748.                 if OptionKeyWasDown then begin
  1749.                         gstr := concat(gstr, long2str(tag), '  ', long2str(ftype), '  ', long2str(N), '  ', long2str(value), crStr);
  1750.                         ShowMessage(gstr);
  1751.                     end;
  1752.             end;
  1753.     end;
  1754.  
  1755.  
  1756.     function OpenTiffDirectory (f: integer; DirOffset: LongInt; var TiffInfo: TiffInfoRec; Importing: boolean): boolean;
  1757.         const
  1758.             NoUnit = 1;
  1759.             inch = 2;
  1760.             centimeter = 3;
  1761.         var
  1762.             ByteCount, length, ftype, N, value, BytesPerStrip, SaveFPos: LongInt;
  1763.             err: OSErr;
  1764.             nEntries, i, tag, entry: integer;
  1765.             StripOffsetsArray: array[1..2] of LongInt;
  1766.             xRes, yRes: extended;
  1767.  
  1768.         function GetResolution: extended;
  1769.             var
  1770.                 resolution: array[1..2] of LongInt;
  1771.         begin
  1772.             err := GetFPos(f, SaveFPos);
  1773.             err := SetFPos(f, fsFromStart, value);
  1774.             ByteCount := 8;
  1775.             err := fsread(f, ByteCount, @Resolution);
  1776.             if IntelByteOrder then begin
  1777.                     Swap4Bytes(Resolution[1]);
  1778.                     Swap4Bytes(Resolution[2]);
  1779.                 end;
  1780.             err := SetFPos(f, fsFromStart, SaveFPos);
  1781.             if resolution[2] <> 0 then
  1782.                 GetResolution := resolution[1] / resolution[2]
  1783.             else
  1784.                 GetResolution := 0.0;
  1785.         end;
  1786.  
  1787.     begin
  1788.         if OptionKeyWasDown then
  1789.             gstr := '';
  1790.         xRes := 0.0;
  1791.         err := SetFPos(f, fsFromStart, DirOffset);
  1792.         ByteCount := 2;
  1793.         err := FSRead(f, ByteCount, @nEntries);
  1794.         if CheckIO(err) <> NoErr then begin
  1795.                 OpenTiffDirectory := false;
  1796.                 exit(OpenTiffDirectory);
  1797.             end;
  1798.         if IntelByteOrder then
  1799.             Swap2Bytes(nEntries);
  1800.         with TiffInfo do begin
  1801.                 width := 0;
  1802.                 height := 0;
  1803.                 BitsPerPixel := 8;
  1804.                 SamplesPerPixel:=1;
  1805.                 PlanarConfig := 1;
  1806.                 OffsetToData := 0;
  1807.                 Resolution := 0.0;
  1808.                 ResUnits := tNoUnits;
  1809.                 OffsetToColorMap := 0;
  1810.                 OffsetToImageHeader := -1;
  1811.                 StripOffsetsArray[1] := 0;
  1812.                 for entry := 1 to nEntries do begin
  1813.                         GetTiffEntry(f, tag, N, value);
  1814.                         if tag = 0 then begin
  1815.                                 PutError('Invalid TIFF format.');
  1816.                                 OpenTiffDirectory := false;
  1817.                                 exit(OpenTiffDirectory)
  1818.                             end;
  1819.                         case tag of
  1820.                             ImageWidth: 
  1821.                                 width := value;
  1822.                             ImageLength: 
  1823.                                 height := value;
  1824.                             BitsPerSample:  begin
  1825.                                     if N = 1 then
  1826.                                         BitsPerPixel := value;
  1827.                                     if value = 1 then begin
  1828.                                             PutError('NIH Image cannot open 1-bit TIFF files.');
  1829.                                             OpenTiffDirectory := false;
  1830.                                             exit(OpenTiffDirectory)
  1831.                                         end;
  1832.                                     if (value = 16) and not importing then begin
  1833.                                             PutError('Use Import to open 16-bit TIFF files.');
  1834.                                             OpenTiffDirectory := false;
  1835.                                             exit(OpenTiffDirectory)
  1836.                                         end;
  1837.                                 end;
  1838.                             SamplesPerPixelTag:
  1839.                                 if (value = 1) or (value = 3) then
  1840.                                      SamplesPerPixel:=value
  1841.                                 else begin
  1842.                                     PutError('NIH Image can only open TIFF files with 1 or 3 samples per pixel.');
  1843.                                     OpenTiffDirectory := false;
  1844.                                     exit(OpenTiffDirectory)
  1845.                                 end;
  1846.                             PlanarConfigTag:
  1847.                                 PlanarConfig := value;
  1848.                             Compression: 
  1849.                                 if value <> 1 then begin
  1850.                                         PutError('NIH Image cannot open compressed TIFF files.');
  1851.                                         OpenTiffDirectory := false;
  1852.                                         exit(OpenTiffDirectory)
  1853.                                     end;
  1854.                             PhotoInterp: 
  1855.                                 ZeroIsBlack := value = 1;
  1856.                             StripOffsets: 
  1857.                                 if N = 1 then
  1858.                                     OffsetToData := value
  1859.                                 else begin
  1860.                                         err := GetFPos(f, SaveFPos);
  1861.                                         err := SetFPos(f, fsFromStart, value);
  1862.                                         ByteCount := 8;
  1863.                                         err := fsread(f, ByteCount, @StripOffsetsArray);
  1864.                                         if IntelByteOrder then begin
  1865.                                                 Swap4Bytes(StripOffsetsArray[1]);
  1866.                                                 Swap4Bytes(StripOffsetsArray[2]);
  1867.                                             end;
  1868.                                         err := SetFPos(f, fsFromStart, SaveFPos);
  1869.                                     end;
  1870.                             RowsPerStrip: 
  1871.                                 if (OffsetToData=0) and (value < height) then begin
  1872.                                         BytesPerStrip := value * width;
  1873.                                         if BitsPerPixel = 16 then
  1874.                                             BytesPerStrip := BytesPerStrip * 2
  1875.                                         else if SamplesPerPixel = 3 then
  1876.                                             BytesPerStrip := BytesPerStrip * 3;
  1877.                                         if StripOffsetsArray[1] = 0 then begin
  1878.                                                 PutError('Invalid TIFF directory.');
  1879.                                                 OpenTiffDirectory := false;
  1880.                                                 exit(OpenTiffDirectory)
  1881.                                             end;
  1882.                                         if StripOffsetsArray[2] <> (StripOffsetsArray[1] + BytesPerStrip) then begin
  1883.                                                 PutError('NIH Image cannot open TIFF files with discontiguous strips.');
  1884.                                                 OpenTiffDirectory := false;
  1885.                                                 exit(OpenTiffDirectory)
  1886.                                             end;
  1887.                                         OffsetToData := StripOffsetsArray[1];
  1888.                                     end;
  1889.                             XResolution: 
  1890.                                 XRes := GetResolution;
  1891.                             YResolution:  begin
  1892.                                     yRes := GetResolution;
  1893.                                     if (xRes = yRes) and (xRes > 0.0) then begin
  1894.                                             resolution := xRes;
  1895.                                             ResUnits := tInches;
  1896.                                         end;
  1897.                                 end;
  1898.                             ResolutionUnit: 
  1899.                                 case value of
  1900.                                     NoUnit: 
  1901.                                         ResUnits := tNoUnits;
  1902.                                     Centimeter: 
  1903.                                         ResUnits := tCentimeters;
  1904.                                     otherwise
  1905.                                 end;
  1906.                             ColorMapTag: 
  1907.                                 if N = 768 then
  1908.                                     OffsetToColorMap := value;
  1909.                             ImageHdrTag: 
  1910.                                 OffsetToImageHeader := value;
  1911.                             otherwise
  1912.                         end;
  1913.                     end; {for}
  1914.                 if OffsetToData = 0 then
  1915.                     OffsetToData := StripOffsetsArray[1];
  1916.                 ByteCount := 4;
  1917.                 err := FSRead(f, ByteCount, @NextIFD);
  1918.                 if IntelByteOrder then
  1919.                     Swap4Bytes(NextIFD);
  1920.                 if OptionKeyWasDown then begin
  1921.                         gstr := concat(gstr, 'Next IFD=', long2str(NextIFD));
  1922.                         ShowMessage(gstr);
  1923.                     end;
  1924.                 if width = 0 then begin
  1925.                         PutError('Error opening TIFF directory');
  1926.                         OpenTiffDirectory := false;
  1927.                         exit(OpenTiffDirectory)
  1928.                     end;
  1929.             end; {with}
  1930.         OpenTiffDirectory := true;
  1931.     end;
  1932.  
  1933.  
  1934.     procedure SaveTiffColorMap (f: integer; ImageDataSize: LongInt);
  1935.         var
  1936.             i: integer;
  1937.             err: OSErr;
  1938.             ColorMap: TiffColorMapType;
  1939.             ColorMapSize: LongInt;
  1940.     begin
  1941.         LoadLUT(info^.cTable);
  1942.         if ScreenDepth=8 then begin
  1943.             for i := 0 to 255 do
  1944.                 with cScreenPort^.portPixMap^^.pmTable^^.ctTable[i].rgb do begin
  1945.                     ColorMap[1, i] := red;
  1946.                     ColorMap[2, i] := green;
  1947.                     ColorMap[3, i] := blue;
  1948.                     end;
  1949.         end else begin
  1950.             for i := 0 to 255 do
  1951.                 with info^.cTable[i].rgb do begin
  1952.                     ColorMap[1, i] := red;
  1953.                     ColorMap[2, i] := green;
  1954.                     ColorMap[3, i] := blue;
  1955.                     end;
  1956.         end;
  1957.         err := SetFPos(f, FSFromStart, HeaderSize + TiffDirSize + ImageDataSize);
  1958.         ColorMapSize := SizeOf(ColorMap);
  1959.         err := fswrite(f, ColorMapSize, @ColorMap);
  1960.         if CheckIO(err) <> 0 then
  1961.             beep;
  1962.     end;
  1963.  
  1964.  
  1965.     procedure GetTiffColorMap (f: integer);
  1966.         var
  1967.             i: integer;
  1968.             ByteCount: LongInt;
  1969.             err: OSErr;
  1970.             ColorMap: TiffColorMapType;
  1971.     begin
  1972.         with info^ do begin
  1973.                 ByteCount := SizeOf(ColorMap);
  1974.                 err := SetFPos(f, fsFromStart, ColorMapOffset);
  1975.                 err := fsRead(f, ByteCount, @ColorMap);
  1976.                 if err = NoErr then begin
  1977.                         if IntelByteOrder then
  1978.                             for i := 0 to 255 do begin
  1979.                                     Swap2Bytes(ColorMap[1, i]);
  1980.                                     Swap2Bytes(ColorMap[2, i]);
  1981.                                     Swap2Bytes(ColorMap[3, i]);
  1982.                                 end;
  1983.                         for i := 0 to 255 do
  1984.                             with cTable[i].rgb do begin
  1985.                                     red := ColorMap[1, i];
  1986.                                     green := ColorMap[2, i];
  1987.                                     blue := ColorMap[3, i];
  1988.                                 end;
  1989.                         LoadLUT(cTable);
  1990.                         LUTMode := ColorLut;
  1991.                         SetupPseudocolor;
  1992.                         IdentityFunction := false;
  1993.                         if isGrayScaleLUT then begin
  1994.                                 info^.LutMode := CustomGrayScale;
  1995.                                 DrawMap;
  1996.                             end;
  1997.                     end
  1998.                 else
  1999.                     beep;
  2000.             end;{with}
  2001.     end;
  2002.  
  2003.  
  2004.     function SaveTiffDir (f, slines, sPixelsPerLine: integer; SavingSelection: boolean; ctabSize, ImageDataSize: LongInt): OSErr;
  2005.         var
  2006.             i: integer;
  2007.             err: OSErr;
  2008.             SavingStack, SavingRGBStack: boolean;
  2009.             ByteCount, width, height: LongInt;
  2010.             TiffInfo1: record
  2011.                     Header: TiffHdr;   {8}
  2012.                     nEntries: integer; {2}
  2013.                     TiffDir: array[1..9] of TiffEntry; {108}
  2014.                 end;
  2015.             ColorMapEntry: TiffEntry;  {12 (Optional)}
  2016.             TiffInfo2: record
  2017.                     ImageHdrEntry: TiffEntry;  {12}
  2018.                     NextIFD: LongInt;  {4}
  2019.                     BitsPerPixelData: array[1..3] of integer; {6} {only used for RGB files}
  2020.                     filler: array[1..TiffFillerSize] of integer; {116}
  2021.                 end;
  2022.             BitsPerSampleData: record
  2023.                 rBitsPerSample, gBitsPerSample, bBitsPerSample:integer;
  2024.             end;
  2025.     begin
  2026.         with info^ do begin
  2027.             SavingStack := false;
  2028.             SavingRGBStack := false;
  2029.             if StackInfo <> nil then
  2030.                 SavingStack := StackInfo^.nSlices > 1;
  2031.             if SavingStack then
  2032.                 if (StackInfo^.StackType = rgbStack) and (StackInfo^.nSlices = 3) then begin
  2033.                     SavingRGBStack := true;
  2034.                     ctabSize := 0;
  2035.                 end;
  2036.             if SavingSelection then begin
  2037.                     width := sPixelsPerLine;
  2038.                     height := sLines
  2039.                 end
  2040.             else begin
  2041.                     width := PixelsPerLine;
  2042.                     height := nLines
  2043.                 end;
  2044.             with TiffInfo1 do begin
  2045.                     with header do begin
  2046.                             ByteOrder := 'MM';
  2047.                             Version := 42;
  2048.                             FirstIFDOffset := 8;
  2049.                         end;
  2050.                     if ctabSize > 0 then
  2051.                         nEntries := 11
  2052.                     else
  2053.                         nEntries := 10;
  2054.                     for i := 1 to 9 do
  2055.                         with TiffDir[i] do begin
  2056.                                 ftype := 3;
  2057.                                 length := 1
  2058.                             end;
  2059.                     with TiffDir[1] do begin
  2060.                             TagField := NewSubfileType;
  2061.                             ftype := 4;
  2062.                             offset := 0;
  2063.                         end;
  2064.                     with TiffDir[2] do begin
  2065.                             TagField := ImageWidth;
  2066.                             offset := bsl(width, 16);
  2067.                         end;
  2068.                     with TiffDir[3] do begin
  2069.                             TagField := ImageLength;
  2070.                             offset := bsl(height, 16);
  2071.                         end;
  2072.                     with TiffDir[4] do begin
  2073.                             TagField := BitsPerSample;
  2074.                             if SavingRGBStack then begin
  2075.                                 ftype := 3;
  2076.                                 length := 3;
  2077.                                 offset := SizeOf(TiffInfo1) + SizeOf(TiffEntry) + SizeOf(LongInt);
  2078.                                 with TiffInfo2 do
  2079.                                     for i := 1 to 3 do
  2080.                                         BitsPerPixelData[i] := 8;
  2081.                             end else begin
  2082.                                 offset := bsl(8, 16);
  2083.                                 with TiffInfo2 do
  2084.                                     for i := 1 to 3 do
  2085.                                         BitsPerPixelData[i] := 0;
  2086.                             end;
  2087.                         end;
  2088.                     with TiffDir[5] do begin
  2089.                             TagField := PhotoInterp;
  2090.                             if SavingRGBStack then
  2091.                                 offset := bsl(2, 16)
  2092.                             else if ctabSize > 0 then
  2093.                                 offset := bsl(3, 16)
  2094.                             else
  2095.                                 offset := 0;
  2096.                         end;
  2097.                     with TiffDir[6] do begin
  2098.                             TagField := StripOffsets;
  2099.                             ftype := 4;
  2100.                             offset := TiffDirSize + HeaderSize;
  2101.                         end;
  2102.                     with TiffDir[7] do begin
  2103.                             TagField := SamplesPerPixelTag;
  2104.                             if SavingRGBStack then
  2105.                                 offset := bsl(3, 16)
  2106.                             else
  2107.                                 offset := bsl(1, 16);
  2108.                         end;
  2109.                     with TiffDir[8] do begin
  2110.                             TagField := RowsPerStrip;
  2111.                             offset := bsl(height, 16);
  2112.                         end;
  2113.                     with TiffDir[9] do begin
  2114.                             TagField := StripByteCount;
  2115.                             ftype := 4;
  2116.                             if SavingRGBStack then
  2117.                                 offset := width * height * 3
  2118.                             else
  2119.                                 offset := width * height;
  2120.                         end;
  2121.                 end;
  2122.             ByteCount := SizeOf(TiffInfo1);
  2123.             err := SetFPos(f, FSFromStart, 0);
  2124.             err := FSWrite(f, ByteCount, @TiffInfo1);
  2125.             if CheckIO(err) <> NoErr then begin
  2126.                     SaveTiffDir := err;
  2127.                     exit(SaveTiffDir);
  2128.                 end;
  2129.             if ctabSize > 0 then
  2130.                 with ColorMapEntry do begin
  2131.                         TagField := ColorMapTag;
  2132.                         ftype := 3;
  2133.                         length := 768;
  2134.                         offset := HeaderSize + TiffDirSize + ImageDataSize;
  2135.                         ByteCount := SizeOf(ColorMapEntry);
  2136.                         err := FSWrite(f, ByteCount, @ColorMapEntry);
  2137.                         if CheckIO(err) <> NoErr then begin
  2138.                                 SaveTiffDir := err;
  2139.                                 exit(SaveTiffDir);
  2140.                             end;
  2141.                     end;
  2142.             with TiffInfo2 do begin
  2143.                     with ImageHdrEntry do begin
  2144.                             TagField := ImageHdrTag;
  2145.                             ftype := 3;
  2146.                             length := 256;
  2147.                             offset := TiffDirSize;
  2148.                         end;
  2149.                     NextIFD := 0;
  2150.                     if SavingStack then
  2151.                         NextIFD := HeaderSize + TiffDirSize + ImageDataSize + ctabSize;
  2152.                     for i := 1 to TiffFillerSize do
  2153.                         filler[i] := 0;
  2154.                 end;
  2155.             end; {with info^}
  2156.         ByteCount := SizeOf(TiffInfo2);
  2157.         err := FSWrite(f, ByteCount, @TiffInfo2);
  2158.         SaveTiffDir := CheckIO(err);
  2159.     end;
  2160.  
  2161.  
  2162.     function WriteExtraTiffIFDs (f: integer; ImageDataSize, cTabSize: LongInt): integer;
  2163.         var
  2164.             IFD, entry: integer;
  2165.             StackIFD: StackIFDType;
  2166.             err: OSErr;
  2167.             IFDoffset, SliceOffset, ByteCount: LongInt;
  2168.     begin
  2169.         with info^, StackInfo^, StackIFD do begin
  2170.                 IFDoffset := HeaderSize + TiffDirSize + ImageDataSize + ctabSize;
  2171.                 err := SetFPos(f, FSFromStart, IFDoffset);
  2172.                 SliceOffset := HeaderSize + TiffDirSize + ImageSize;
  2173.                 for IFD := 2 to nSlices do  {IFD=Image File Directory}
  2174.                     begin
  2175.                         nEntries := 6;
  2176.                         for entry := 1 to nEntries do
  2177.                             with TiffDir[entry] do begin
  2178.                                     ftype := 3;
  2179.                                     length := 1
  2180.                                 end;
  2181.                         with TiffDir[1] do begin
  2182.                                 TagField := NewSubfileType;
  2183.                                 ftype := 4;
  2184.                                 offset := 0;
  2185.                             end;
  2186.                         with TiffDir[2] do begin
  2187.                                 TagField := ImageWidth;
  2188.                                 offset := bsl(PixelsPerLine, 16);
  2189.                             end;
  2190.                         with TiffDir[3] do begin
  2191.                                 TagField := ImageLength;
  2192.                                 offset := bsl(nLines, 16);
  2193.                             end;
  2194.                         with TiffDir[4] do begin
  2195.                                 TagField := BitsPerSample;
  2196.                                 offset := bsl(8, 16);
  2197.                             end;
  2198.                         with TiffDir[5] do begin
  2199.                                 TagField := PhotoInterp;
  2200.                                 offset := 0;
  2201.                             end;
  2202.                         with TiffDir[6] do begin
  2203.                                 TagField := StripOffsets;
  2204.                                 ftype := 4;
  2205.                                 offset := SliceOffset;
  2206.                             end;
  2207.                         SliceOffset := SliceOffset + ImageSize;
  2208.                         IFDoffset := IFDoffset + SizeOf(StackIFD);
  2209.                         if IFD <> nSlices then
  2210.                             NextIFD := IFDoffset
  2211.                         else
  2212.                             NextIFD := 0;
  2213.                         ByteCount := SizeOf(StackIFD);
  2214.                         err := fswrite(f, ByteCount, @StackIFD);
  2215.                         if err <> NoErr then begin
  2216.                                 WriteExtraTiffIFDs := err;
  2217.                                 exit(WriteExtraTiffIFDs);
  2218.                             end;
  2219.                     end; {for}
  2220.             end; {with}
  2221.         WriteExtraTiffIFDs := NoErr;
  2222.     end;
  2223.  
  2224.  
  2225.     procedure SaveLUT (fname: str255; RefNum: integer);
  2226.         var
  2227.             err: integer;
  2228.             TheInfo: FInfo;
  2229.             LUT: array[1..3] of packed array[0..255] of byte;
  2230.             i, f: integer;
  2231.             ByteCount: LongInt;
  2232.             tempRGB:rgbColor;
  2233.     begin
  2234.         err := GetFInfo(fname, RefNum, TheInfo);
  2235.         case err of
  2236.             NoErr: 
  2237.                 if TheInfo.fdType <> 'ICOL' then begin
  2238.                         TypeMismatch(fname);
  2239.                         exit(SaveLUT)
  2240.                     end;
  2241.             FNFerr:  begin
  2242.                     err := create(fname, RefNum, 'Imag', 'ICOL');
  2243.                     if CheckIO(err) <> 0 then
  2244.                         exit(SaveLUT);
  2245.                 end;
  2246.             otherwise
  2247.                 if CheckIO(err) <> 0 then
  2248.                     exit(SaveLUT);
  2249.         end;
  2250.         DisableDensitySlice;
  2251.         LoadLUT(Info^.cTable);
  2252.         if ScreenDepth = 8 then begin
  2253.             for i := 0 to 255 do
  2254.                 with cScreenPort^.portPixMap^^.pmTable^^.ctTable[i].rgb do begin
  2255.                         LUT[1, i] := band(bsr(red, 8), 255);
  2256.                         LUT[2, i] := band(bsr(green, 8), 255);
  2257.                         LUT[3, i] := band(bsr(blue, 8), 255);
  2258.                     end;
  2259.         end else begin
  2260.             for i := 0 to 255 do
  2261.                 with info^.cTable[i].rgb do begin
  2262.                         LUT[1, i] := band(bsr(red, 8), 255);
  2263.                         LUT[2, i] := band(bsr(green, 8), 255);
  2264.                         LUT[3, i] := band(bsr(blue, 8), 255);
  2265.                     end;
  2266.         end;
  2267.         err := fsopen(fname, RefNum, f);
  2268.         if CheckIO(err) <> 0 then
  2269.             exit(SaveLUT);
  2270.         err := SetFPos(f, FSFromStart, 0);
  2271.         ByteCount := SizeOf(LUT);
  2272.         err := fswrite(f, ByteCount, @LUT);
  2273.         if CheckIO(err) <> 0 then begin
  2274.                 err := fsclose(f);
  2275.                 err := FSDelete(fname, RefNum);
  2276.                 exit(SaveLUT)
  2277.             end;
  2278.         err := SetEof(f, ByteCount);
  2279.         err := fsclose(f);
  2280.         err := GetFInfo(fname, RefNum, TheInfo);
  2281.         if TheInfo.fdCreator <> 'Imag' then begin
  2282.                 TheInfo.fdCreator := 'Imag';
  2283.                 err := SetFInfo(fname, RefNum, TheInfo);
  2284.             end;
  2285.         err := FlushVol(nil, RefNum);
  2286.     end;
  2287.  
  2288.  
  2289.     procedure SaveColorTable (fname: str255; RefNum: integer);
  2290.         var
  2291.             err: integer;
  2292.             TheInfo: FInfo;
  2293.             i, f: integer;
  2294.             ByteCount: LongInt;
  2295.             hdr: PaletteHeader;
  2296.     begin
  2297.         with info^ do
  2298.             err := GetFInfo(fname, RefNum, TheInfo);
  2299.         case err of
  2300.             NoErr: 
  2301.                 if TheInfo.fdType <> 'ICOL' then begin
  2302.                         TypeMismatch(fname);
  2303.                         exit(SaveColorTable)
  2304.                     end;
  2305.             FNFerr:  begin
  2306.                     err := create(fname, RefNum, 'Imag', 'ICOL');
  2307.                     if CheckIO(err) <> 0 then
  2308.                         exit(SaveColorTable);
  2309.                 end;
  2310.             otherwise
  2311.                 if CheckIO(err) <> 0 then
  2312.                     exit(SaveColorTable);
  2313.         end;
  2314.         with info^ do begin
  2315.                 InitPaletteHeader(hdr);
  2316.                 err := fsopen(fname, RefNum, f);
  2317.                 if CheckIO(err) <> 0 then
  2318.                     exit(SaveColorTable);
  2319.                 err := SetFPos(f, FSFromStart, 0);
  2320.                 ByteCount := SizeOf(PaletteHeader);
  2321.                 if ByteCount <> 32 then
  2322.                     PutError('Palette header size <> 32.');
  2323.                 err := fswrite(f, ByteCount, @hdr);
  2324.                 ByteCount := nColors;
  2325.                 err := fswrite(f, ByteCount, @redLUT);
  2326.                 ByteCount := nColors;
  2327.                 err := fswrite(f, ByteCount, @greenLUT);
  2328.                 ByteCount := nColors;
  2329.                 err := fswrite(f, ByteCount, @blueLUT);
  2330.                 if CheckIO(err) <> 0 then begin
  2331.                         err := fsclose(f);
  2332.                         err := FSDelete(fname, RefNum);
  2333.                         exit(SaveColorTable)
  2334.                     end;
  2335.                 err := SetEOF(f, SizeOf(PaletteHeader) + 3 * nColors);
  2336.                 err := fsclose(f);
  2337.                 err := GetFInfo(fname, RefNum, TheInfo);
  2338.                 if TheInfo.fdCreator <> 'Imag' then begin
  2339.                         TheInfo.fdCreator := 'Imag';
  2340.                         err := SetFInfo(fname, RefNum, TheInfo);
  2341.                     end;
  2342.                 err := FlushVol(nil, RefNum);
  2343.             end; {with info^}
  2344.     end;
  2345.  
  2346.  
  2347.     procedure SaveOutline (fname: str255; RefNum: integer);
  2348.         var
  2349.             err: integer;
  2350.             TheInfo: FInfo;
  2351.             i, f: integer;
  2352.             ByteCount, DataSize: LongInt;
  2353.             hdr: RoiHeader;
  2354.             SaveCoordinates: boolean;
  2355.             dX1, dY1, dX2, dY2: extended;
  2356.     begin
  2357.         with info^ do begin
  2358.                 if not RoiShowing then begin
  2359.                         PutError('No outline available to save.');
  2360.                         exit(SaveOutline);
  2361.                     end;
  2362.                 if (RoiType = FreeLineRoi) or (RoiType = SegLineRoi) then begin
  2363.                         PutError('Freehand and segmented line selections cannot be saved.');
  2364.                         exit(SaveOutline);
  2365.                     end;
  2366.                 SaveCoordinates := (RoiType = PolygonRoi) or (RoiType = FreehandRoi) or (RoiType = TracedRoi);
  2367.                 if SaveCoordinates then
  2368.                     if not CoordinatesAvailableMsg then begin
  2369.                             exit(SaveOutline);
  2370.                         end;
  2371.                 err := GetFInfo(fname, RefNum, TheInfo);
  2372.                 case err of
  2373.                     NoErr: 
  2374.                         if TheInfo.fdType <> 'Iout' then begin
  2375.                                 TypeMismatch(fname);
  2376.                                 exit(SaveOutline)
  2377.                             end;
  2378.                     FNFerr:  begin
  2379.                             err := create(fname, RefNum, 'Imag', 'Iout');
  2380.                             if CheckIO(err) <> 0 then
  2381.                                 exit(SaveOutline);
  2382.                         end;
  2383.                     otherwise
  2384.                         if CheckIO(err) <> 0 then
  2385.                             exit(SaveOutline);
  2386.                 end;
  2387.                 with hdr do begin
  2388.                         rID := 'Iout';
  2389.                         rVersion := version;
  2390.                         rRoiType := RoiType;
  2391.                         rRoiRect := RoiRect;
  2392.                         rNCoordinates := nCoordinates;
  2393.                         GetLoi(dX1, dY1, dX2, dY2);
  2394.                         rX1:=dX1; rY1:=dY1; rX2:=dX2; rY2:=dY2;
  2395.                         rLineWidth := LineWidth;
  2396.                         for i := 1 to 14 do
  2397.                             rUnused[i] := 0;
  2398.                     end;
  2399.                 err := fsopen(fname, RefNum, f);
  2400.                 if CheckIO(err) <> 0 then
  2401.                     exit(SaveOutline);
  2402.                 err := SetFPos(f, FSFromStart, 0);
  2403.                 ByteCount := SizeOf(RoiHeader);
  2404.                 if ByteCount <> 64 then
  2405.                     PutError('Roi header size <> 32.');
  2406.                 err := fswrite(f, ByteCount, @hdr);
  2407.                 if SaveCoordinates then begin
  2408.                         ByteCount := nCoordinates * 2;
  2409.                         err := fswrite(f, ByteCount, ptr(xCoordinates));
  2410.                         ByteCount := nCoordinates * 2;
  2411.                         err := fswrite(f, ByteCount, ptr(yCoordinates));
  2412.                         DataSize := nCoordinates * 4;
  2413.                     end
  2414.                 else
  2415.                     DataSize := 0;
  2416.                 if CheckIO(err) <> 0 then begin
  2417.                         err := fsclose(f);
  2418.                         err := FSDelete(fname, RefNum);
  2419.                         exit(SaveOutline)
  2420.                     end;
  2421.                 err := SetEOF(f, SizeOf(RoiHeader) + DataSize);
  2422.                 err := fsclose(f);
  2423.                 err := GetFInfo(fname, RefNum, TheInfo);
  2424.                 if TheInfo.fdCreator <> 'Imag' then begin
  2425.                         TheInfo.fdCreator := 'Imag';
  2426.                         err := SetFInfo(fname, RefNum, TheInfo);
  2427.                     end;
  2428.                 err := FlushVol(nil, RefNum);
  2429.             end; {with info^}
  2430.     end;
  2431.  
  2432.  
  2433.     procedure OpenOutline (fname: str255; RefNum: integer);
  2434.         var
  2435.             err, f, i: integer;
  2436.             count: LongInt;
  2437.             hdr: RoiHeader;
  2438.             okay: boolean;
  2439.     begin
  2440.         if Info = NoInfo then begin
  2441.                 if (NewPicWidth * NewPicHeight) <= UndoBufSize then begin
  2442.                         if not NewPicWindow('Untitled', NewPicWidth, NewPicHeight) then
  2443.                             exit(OpenOutline)
  2444.                     end
  2445.                 else begin
  2446.                         beep;
  2447.                         exit(OpenOutline)
  2448.                     end;
  2449.             end;
  2450.         KillRoi;
  2451.         err := fsopen(fname, RefNum, f);
  2452.         with info^, hdr do begin
  2453.                 count := SizeOf(RoiHeader);
  2454.                 err := fsread(f, count, @hdr);
  2455.                 if rID <> 'Iout' then begin
  2456.                         err := fsclose(f);
  2457.                         PutError('File is corrupted.');
  2458.                         exit(OpenOutline)
  2459.                     end;
  2460.                 if (rRoiRect.right > PicRect.right) or (rRoiRect.bottom > PicRect.bottom) then begin
  2461.                         err := fsclose(f);
  2462.                         PutError('Image is too small for the outline.');
  2463.                         exit(OpenOutline)
  2464.                     end;
  2465.                 case rRoiType of
  2466.                     LineRoi:  begin
  2467.                             LX1 := rX1;
  2468.                             LY1 := rY1;
  2469.                             LX2 := rX2;
  2470.                             LY2 := rY2;
  2471.                             RoiType := LineRoi;
  2472.                             MakeRegion;
  2473.                             SetupUndo;
  2474.                             RoiShowing := true;
  2475.                         end;
  2476.                     RectRoi, OvalRoi:  begin
  2477.                             RoiType := rRoiType;
  2478.                             RoiRect := rRoiRect;
  2479.                             MakeRegion;
  2480.                             SetupUndo;
  2481.                             RoiShowing := true;
  2482.                         end;
  2483.                     PolygonRoi, FreehandRoi, TracedRoi: 
  2484.                         if (rNCoordinates > 2) and (rNCoordinates <= MaxCoordinates) then begin
  2485.                                 count := rNCoordinates * 2;
  2486.                                 err := fsread(f, count, ptr(xCoordinates));
  2487.                                 count := rNCoordinates * 2;
  2488.                                 err := fsread(f, count, ptr(yCoordinates));
  2489.                                 if CheckIO(err) = 0 then begin
  2490.                                         nCoordinates := rNCoordinates;
  2491.                                         SelectionMode := NewSelection;
  2492.                                         if rVersion >= 148 then
  2493.                                             for i := 1 to nCoordinates do
  2494.                                                 with rRoiRect do begin
  2495.                                                         xCoordinates^[i] := xCoordinates^[i] + left;
  2496.                                                         yCoordinates^[i] := yCoordinates^[i] + top;
  2497.                                                     end;
  2498.                                         MakeOutline(rRoiType);
  2499.                                         SetupUndo;
  2500.                                     end;
  2501.                             end;
  2502.                 end;
  2503.             end;
  2504.         err := fsclose(f);
  2505.     end;
  2506.  
  2507.  
  2508.     function GetTIFFParameters (name: str255; RefNum: integer; var HasColorMap: boolean): boolean;
  2509.         var
  2510.             err: OSErr;
  2511.             f: integer;
  2512.             DirOffset: LongInt;
  2513.             TiffInfo: TiffInfoRec;
  2514.     begin
  2515.         GetTIFFParameters := false;
  2516.         HasColorMap := false;
  2517.         err := fsopen(name, RefNum, f);
  2518.         if err <> NoErr then
  2519.             exit(GetTIFFParameters);
  2520.         if not OpenTiffHeader(f, DirOffset) then begin
  2521.                 err := fsclose(f);
  2522.                 exit(GetTIFFParameters)
  2523.             end;
  2524.         if not OpenTiffDirectory(f, DirOffset, TiffInfo, true) then begin
  2525.                 err := fsclose(f);
  2526.                 exit(GetTIFFParameters)
  2527.             end;
  2528.         with TiffInfo do begin
  2529.                 ImportCustomWidth := width;
  2530.                 ImportCustomHeight := height;
  2531.                 ImportCustomOffset := OffsetToData;
  2532.                 ImportAutoScale:=true;
  2533.                 if BitsPerPixel = 16 then begin
  2534.                         ImportCustomDepth := SixteenBitsUnsigned;
  2535.                         ImportSwapBytes := IntelByteOrder;
  2536.                     end
  2537.                 else begin
  2538.                         ImportCustomDepth := EightBits;
  2539.                         ImportInvert := ZeroIsBlack;
  2540.                     end;
  2541.                 HasColorMap := OffsetToColorMap > 0;
  2542.             end;
  2543.         if ImportCustomDepth = EightBits then begin
  2544.             WhatToImport := ImportTiff;
  2545.             WhatToOpen := OpenTiff
  2546.         end else begin
  2547.             WhatToImport := ImportCustom;
  2548.             WhatToOpen := OpenCustom
  2549.         end;
  2550.         err := fsclose(f);
  2551.         GetTIFFParameters := true;
  2552.     end;
  2553.  
  2554.  
  2555.     procedure GetXUnits (UnitsKind: UnitsType);
  2556.     begin
  2557.         with info^ do
  2558.             case UnitsKind of
  2559.                 Nanometers: 
  2560.                     xUnit := 'nm';
  2561.                 Micrometers: 
  2562.                     xUnit := 'µm';
  2563.                 Millimeters: 
  2564.                     xUnit := 'mm';
  2565.                 Centimeters: 
  2566.                     xUnit := 'cm';
  2567.                 Meters: 
  2568.                     xUnit := 'meter';
  2569.                 Kilometers: 
  2570.                     xUnit := 'km';
  2571.                 Inches: 
  2572.                     xUnit := 'inch';
  2573.                 feet: 
  2574.                     xUnit := 'ft';
  2575.                 Miles: 
  2576.                     xUnit := 'mile';
  2577.                 Pixels: 
  2578.                     xUnit := 'pixel';
  2579.                 otherwise
  2580.                     ;
  2581.             end;
  2582.     end;
  2583.  
  2584.  
  2585.     procedure GetUnitsKInd (var UnitsKind: UnitsType; var UnitsPerCM: extended);
  2586.     begin
  2587.         with info^ do begin
  2588.                 if xunit = 'nm' then begin
  2589.                         UnitsKind := Nanometers;
  2590.                         UnitsPerCm := 10000000.0;
  2591.                     end
  2592.                 else if xUnit = 'µm' then begin
  2593.                         UnitsKind := Micrometers;
  2594.                         UnitsPerCm := 10000.0;
  2595.                     end
  2596.                 else if xUnit = 'mm' then begin
  2597.                         UnitsKind := Millimeters;
  2598.                         UnitsPerCm := 10.0;
  2599.                     end
  2600.                 else if xUnit = 'cm' then begin
  2601.                         UnitsKind := Centimeters;
  2602.                         UnitsPerCm := 1.0;
  2603.                     end
  2604.                 else if xUnit = 'meter' then begin
  2605.                         UnitsKind := Meters;
  2606.                         UnitsPerCm := 0.01;
  2607.                     end
  2608.                 else if xUnit = 'km' then begin
  2609.                         UnitsKind := Kilometers;
  2610.                         UnitsPerCm := 0.00001;
  2611.                     end
  2612.                 else if xUnit = 'inch' then begin
  2613.                         UnitsKind := Inches;
  2614.                         UnitsPerCm := 0.3937;
  2615.                     end
  2616.                 else if xUnit = 'ft' then begin
  2617.                         UnitsKind := feet;
  2618.                         UnitsPerCm := 0.0328083;
  2619.                     end
  2620.                 else if xUnit = 'mile' then begin
  2621.                         UnitsKind := Miles;
  2622.                         UnitsPerCm := 0.000006213;
  2623.                     end
  2624.                 else if xUnit = 'pixel' then begin
  2625.                         UnitsKind := pixels;
  2626.                         UnitsPerCm := 0.0;
  2627.                         SpatiallyCalibrated := false;
  2628.                     end
  2629.                 else begin
  2630.                         UnitsKind := OtherUnits;
  2631.                         UnitsPerCm := 0.0;
  2632.                     end;
  2633.             end;
  2634.     end;
  2635.     
  2636.  
  2637.     function OpenMovieToolbox:boolean;
  2638.     var
  2639.         result: LongInt;
  2640.         err: OSErr;
  2641.     begin
  2642.         if MovieToolboxInitialized then begin
  2643.             OpenMovieToolbox := true;
  2644.             exit(OpenMovieToolbox);
  2645.         end;
  2646.         if Gestalt(gestaltQuickTime, result) <> noErr then begin
  2647.             ShowMessage('QuickTime Required');
  2648.             OpenMovieToolbox := false;
  2649.             exit(OpenMovieToolbox);
  2650.         end;
  2651.         err := EnterMovies;
  2652.         if (err <> noErr) then begin
  2653.             PutMessage('QuickTime Required');
  2654.             OpenMovieToolbox := false;
  2655.             exit(OpenMovieToolbox);
  2656.         end;
  2657.         MovieToolboxInitialized := true;
  2658.         OpenMovieToolbox := true;
  2659.     end;
  2660.     
  2661.  
  2662.     function OpenQuickTime (name: str255; fRefNum: integer; UseExistingLUT: boolean): boolean;
  2663.     {Written 3/25/94 by Eric Shelden (shelden@umich.edu)}
  2664.         const
  2665.             forwardNormalSpeed = $00010000;
  2666.  
  2667.         var
  2668.             RefNum, picID, hOffset, vOffset, nPICS, i: LongInt;
  2669.             err: OSErr;
  2670.             PicH: PicHandle;
  2671.             h: handle;
  2672.             MemError, Aborted: boolean;
  2673.             FrameRect: rect;
  2674.             movieResRefNum, actualResId, verb: integer;
  2675.             theMovie: Movie;
  2676.             theTrack, videoTrack: Track;
  2677.             theMedia: Media;
  2678.             inTime, trackOffset, trackEnd, sampleTime: TimeValue;
  2679.             mySpec: FSSpec;
  2680.             TheInfo: FInfo;
  2681.             fName: Str255;
  2682.             check: Boolean;
  2683.             trackCount, count: LongInt;
  2684.             mediaType, manuf: OSType;
  2685.             imageCTable: CTabHandle;
  2686.             imageDescH: ImageDescriptionHandle;
  2687.             pInfo: PictInfo;
  2688.             creatorName: str255;
  2689.             SavePort: GrafPtr;
  2690.             SaveGDevice: GDHandle;
  2691.  
  2692.         procedure Abort;
  2693.         begin
  2694.             err := CloseMovieFile(movieResRefNum);
  2695.             exit(OpenQuickTime);
  2696.         end;
  2697.  
  2698.     begin
  2699.         OpenQuickTime := false;
  2700.         check := FALSE;
  2701.         sampleTime := 0;
  2702.         if MaxBlock < MinFree then begin
  2703.                 PutError('Insufficient memory to open QuickTime movie.');
  2704.                 exit(OpenQuickTime);
  2705.             end;
  2706.         ShowWatch;
  2707.         if not OpenMovieToolbox then
  2708.             exit(OpenQuickTime);
  2709.         err := GetFInfo(name, fRefNum, TheInfo);
  2710.         err := FSMakeFSSpec(fRefNum, 0, name, mySpec);
  2711.         err := OpenMovieFile(mySpec, movieResRefNum, fsRdPerm);
  2712.         if (err <> noErr) then begin
  2713.             PutError('QuickTime Error');
  2714.             exit(OpenQuickTime);
  2715.         end;
  2716.         actualResId := DoTheRightThing;
  2717.         err := NewMovieFromFile(theMovie, movieResRefNum, actualResId, nil, newMovieActive, check);
  2718.         trackCount := GetMovieTrackCount(theMovie);
  2719.         videoTrack := nil;
  2720.         for i := 1 to trackCount do begin
  2721.                 videoTrack := GetMovieIndTrack(theMovie, i);
  2722.                 creatorName := '';
  2723.                 GetMediaHandlerDescription(GetTrackMedia(videoTrack), mediaType, creatorName, manuf);
  2724.                 if (mediaType = 'vide') then
  2725.                     i := trackCount + 1
  2726.                 else
  2727.                     videoTrack := nil;
  2728.             end;
  2729.  
  2730.         if (videoTrack = nil) then begin
  2731.                 PutError('No Movie Pictures found.');
  2732.                 abort;
  2733.             end;
  2734.  
  2735.         GetMovieBox(theMovie, FrameRect);
  2736.         with FrameRect do begin
  2737.                 hOffset := left;
  2738.                 vOffset := top;
  2739.                 right := right - hOffset;
  2740.                 bottom := bottom - vOffset;
  2741.                 left := 0;
  2742.                 top := 0;
  2743.             end;
  2744.  
  2745.         with FrameRect do
  2746.             if not NewPicWindow(name, right - left, bottom - top) then
  2747.                 Abort;
  2748.  
  2749.         with info^ do begin
  2750.                 revertable := false;
  2751.                 StackInfo := StackInfoPtr(NewPtr(SizeOf(StackInfoRec)));
  2752.                 if StackInfo = nil then
  2753.                     Abort;
  2754.                 with StackInfo^ do begin
  2755.                         SliceSpacing := 0.0;
  2756.                         nSlices := 1;
  2757.                         CurrentSlice := 1;
  2758.                         PicBaseH[1] := PicBaseHandle;
  2759.                     end;
  2760.             end;
  2761.  
  2762.         trackEnd := GetTrackDuration(videoTrack);
  2763.         trackOffset := GetTrackOffset(videoTrack);
  2764.         inTime := trackOffset;
  2765.         PicH := GetTrackPict(videoTrack, inTime);
  2766.         {
  2767.         verb := returnColorTable;
  2768.         err := GetPictInfo(PicH, pInfo, verb, 256, systemMethod, 0);
  2769.         if not UseExistingLUT then begin
  2770.             LoadColorTable(pInfo.theColorTable);
  2771.             DrawLUT;
  2772.         end;
  2773.         }
  2774.  
  2775.         with info^, Info^.StackInfo^ do begin
  2776.                 SaveGDevice := GetGDevice;
  2777.                 SetGDevice(osGDevice);
  2778.                 GetPort(SavePort);
  2779.                 SetPort(GrafPtr(osPort));
  2780.                 pmBackColor(WhiteIndex);
  2781.                 EraseRect(PicRect);
  2782.                 DrawPicture(PicH, PicRect);
  2783.                 DisposeHandle(handle(PicH));
  2784.                 UpdatePicWindow;
  2785.                 MemError := false;
  2786.                 picID := 0;
  2787.  
  2788.                 while (inTime <> -1) do begin
  2789.                         GetTrackNextInterestingTime(videoTrack, nextTimeMediaSample, inTime, forwardNormalSpeed, inTime, sampleTime);
  2790.                         if (inTime = -1) then
  2791.                             Leave;
  2792.                         picH := GetTrackPict(videoTrack, inTime);
  2793.                         if (PicH = nil) or (ResError <> NoErr) then
  2794.                             Leave;
  2795.                         h := GetBigHandle(PixMapSize);
  2796.  
  2797.                         if h = nil then begin
  2798.                                 if PicH <> nil then
  2799.                                     DisposeHandle(handle(picH));
  2800.                                 MemError := true;
  2801.                                 Leave;
  2802.                             end;
  2803.  
  2804.                         nSlices := nSlices + 1;
  2805.                         CurrentSlice := CurrentSlice + 1;
  2806.                         PicBaseH[CurrentSlice] := h;
  2807.                         SelectSlice(CurrentSlice);
  2808.                         FrameRect := PicH^^.PicFrame;
  2809.  
  2810.                         with FrameRect do begin
  2811.                                 right := right - hOffset;
  2812.                                 bottom := bottom - vOffset;
  2813.                                 left := left - hOffset;
  2814.                                 top := top - vOffset;
  2815.                             end;
  2816.  
  2817.                         EraseRect(PicRect);
  2818.                         if not EqualRect(FrameRect, PicRect) then
  2819.                             BlockMove(PicBaseH[CurrentSlice - 1]^, PicBaseH[CurrentSlice]^, PixMapSize);
  2820.                         DrawPicture(picH, FrameRect);
  2821.                         DisposeHandle(handle(picH));
  2822.                         UpdatePicWindow;
  2823.                         SetGDevice(SaveGDevice);
  2824.                         UpdateTitleBar;
  2825.                         SetGDevice(osGDevice);
  2826.                         Aborted := CommandPeriod;
  2827.  
  2828.                         if Aborted then begin
  2829.                                 beep;
  2830.                                 wait(60);
  2831.                                 Leave;
  2832.                             end;
  2833.  
  2834.                         picID := picID + 1;
  2835.                     end; {for}
  2836.  
  2837.                 err := CloseMovieFile(movieResRefNum);
  2838.                 if MemError then
  2839.                     PutError('Not enough memory to open all images in MooV file.');
  2840.                 CurrentSlice := 1;
  2841.                 SelectSlice(CurrentSlice);
  2842.                 PictureType := PicsFile;
  2843.                 Revertable := false;
  2844.                 SetPort(SavePort);
  2845.                 SetGDevice(SaveGDevice);
  2846.                 UpdateTitleBar;
  2847.                 UpdateWindowsMenuItem;
  2848.                 if not MemError and not Aborted then
  2849.                     OpenQuickTime := true;
  2850.             end; {with}
  2851.  
  2852.     end;
  2853.  
  2854.  
  2855.     procedure SaveAsQuickTime (fname: str255; fRefNum: integer);
  2856.     {Written by Eric A. Shelden (shelden@umich.edu) 3/23/94}
  2857.         const
  2858.             rErr = 'Error Saving QuickTime file.';
  2859.         var
  2860.             err: OSErr;
  2861.             TheInfo: FInfo;
  2862.             replacing: boolean;
  2863.             rRefNum, i, SaveCS: integer;
  2864.             frect: rect;
  2865.             MinFreeRequired: LongInt;
  2866.  
  2867.             theTimeSettings: SCTemporalSettings;
  2868.             theRateSettings: SCDataRateSettings;
  2869.             theSpaceSettings: SCSpatialSettings;
  2870.             myComponentPtr: ptr;
  2871.             framesPerSecond, maxCompressedSize, curSample: longint;
  2872.             myResult: ComponentResult;
  2873.             myComponentInstance: ComponentInstance;
  2874.             mySpec: FSSpec;
  2875.             theSFR: StandardFileReply;
  2876.             resRefNum, resID: integer;
  2877.             theMovie: Movie;
  2878.             movieData: MovieRecord;
  2879.             theTrack: Track;
  2880.             theMedia: Media;
  2881.             trackFrame: Rect;
  2882.             theGWorld: GWorldPtr;
  2883.             compressedData: Handle;
  2884.             compressedDataptr: Ptr;
  2885.             imageDesc: ImageDescriptionHandle;
  2886.             thePixMap: PixMapHandle;
  2887.             check: Boolean;
  2888.             oldPort: CGrafPtr;
  2889.             oldGDeviceH: GDHandle;
  2890.             myTimeScale, actualTime: TimeScale;
  2891.             testflags: integer;
  2892.  
  2893.     begin
  2894.         with info^, Info^.StackInfo^ do begin
  2895.                 if ImageSize > MinFree then
  2896.                     MinFreeRequired := ImageSize
  2897.                 else
  2898.                     MinFreeRequired := MinFree;
  2899.                 if MaxBlock < MinFreeRequired then begin
  2900.                         PutError('Not enough memory available to save in QuickTime format.');
  2901.                         exit(SaveAsQuickTime);
  2902.                     end;
  2903.                 if not OpenMovieToolbox then
  2904.                     exit(SaveAsQuickTime);
  2905.                 err := GetFInfo(fname, fRefNum, TheInfo);
  2906.                 if err = NoErr then
  2907.                     with TheInfo do begin
  2908.                             if (fdType <> 'TIFF') and (fdType <> 'PICT') and (fdType <> 'PICS') and (fdType <> 'MooV') then begin
  2909.                                     TypeMismatch(fname);
  2910.                                     exit(SaveAsQuickTime)
  2911.                                 end;
  2912.                             err := FSDelete(fname, fRefNum);
  2913.                         end;
  2914.  
  2915.                 SaveCS := CurrentSlice;
  2916.                 SetPort(GrafPtr(osPort));
  2917.                 with PicRect do
  2918.                     SetRect(frect, 0, 0, right - left, bottom - top);
  2919.                 ClipRect(frect);
  2920.                 LoadLUT(ctable);
  2921.                 pmForeColor(BlackIndex);
  2922.                 pmBackColor(WhiteIndex);
  2923.                 if OldSystem then begin
  2924.                         RGBForeColor(BlackRGB);
  2925.                         RGBBackColor(WhiteRGB);
  2926.                     end;
  2927.  
  2928.                 testflags := 0;
  2929.                 theGWorld := osPort;
  2930.                 thePixMap := GetGWorldPixMap(theGWorld);
  2931.                 check := LockPixels(thePixMap);
  2932.                 myComponentInstance := OpenDefaultComponent('scdi', 'imag');
  2933.                 {myResult := SCSetTestImagePixMap(myComponentInstance, thePixMap, @frect, testflags);}
  2934.                 myResult := SCRequestSequenceSettings(myComponentInstance);
  2935.                 if (myResult = 1) then begin
  2936.                         myResult := CloseComponent(myComponentInstance);
  2937.                         exit(SaveAsQuickTime);
  2938.                     end;
  2939.                 if (myResult = -50) then begin
  2940.                         myResult := CloseComponent(myComponentInstance);
  2941.                         PutError('Invalid Parameter detected.');
  2942.                         exit(SaveAsQuickTime);
  2943.                     end;
  2944.                 myResult := SCGetInfo(myComponentInstance, 'sptl', ptr(@theSpaceSettings));
  2945.                 myResult := SCGetInfo(myComponentInstance, scTemporalSettingsType, ptr(@theTimeSettings));
  2946.                 myResult := SCGetInfo(myComponentInstance, scDataRateSettingsType, ptr(@theRateSettings));
  2947.                 myResult := CloseComponent(myComponentInstance);
  2948.                 UnlockPixels(thePixMap);
  2949.                 framesPerSecond := longint(theTimeSettings.frameRate);
  2950.                 framesPerSecond := framesPerSecond div 65536;
  2951.                 resRefNum := 0;
  2952.                 theMovie := nil;
  2953.  
  2954.                 ShowWatch;
  2955.  
  2956.                 err := FSMakeFSSpec(fRefNum, 0, fname, mySpec);
  2957.                 err := CreateMovieFile(mySpec, 'TVOD', $FE, createMovieFileDeleteCurFile, resRefNum, theMovie);
  2958.                 if (err <> 0) then begin
  2959.                         PutError(rErr);
  2960.                         exit(SaveAsQuickTime);
  2961.                     end;
  2962.                 trackFrame := fRect;
  2963.                 theTrack := NewMovieTrack(theMovie, FixRatio(trackFrame.right, 1), FixRatio(trackFrame.bottom, 1), kNoVolume);
  2964.                 theMedia := NewTrackMedia(theTrack, 'vide', TimeScale(60), nil, '    ');
  2965.                 err := BeginMediaEdits(theMedia);
  2966.  
  2967.                 check := LockPixels(thePixMap);
  2968.                 err := GetMaxCompressionSize(thePixMap, trackFrame, theSpaceSettings.depth, theSpaceSettings.spatialQuality, theSpaceSettings.codecType, CompressorComponent(theSpaceSettings.codec), maxCompressedSize);
  2969.                 compressedData := NewHandle(maxCompressedSize);
  2970.                 if (compressedData = nil) or (MemError <> 0) then begin
  2971.                         err := EndMediaEdits(theMedia);
  2972.                         if (theMovie <> Movie(0)) then begin
  2973.                                 err := CloseMovieFile(resRefNum);
  2974.                                 DisposeMovie(theMovie);
  2975.                                 PutError(rErr);
  2976.                                 exit(SaveAsQuickTime);
  2977.                             end;
  2978.                     end;
  2979.                 MoveHHi(compressedData);
  2980.                 HLock(compressedData);
  2981.                 compressedDataPtr := StripAddress(compressedData^);
  2982.                 imageDesc := ImageDescriptionHandle(NewHandle(4));
  2983.                 myTimeScale := 60 div framesPerSecond;
  2984.                 GetGWorld(oldPort, oldGDeviceH);
  2985.                 SetGWorld(theGWorld, nil);
  2986.                 for i := 1 to nSlices do begin
  2987.                         CurrentSlice := i;
  2988.                         SelectSlice(CurrentSlice);
  2989.                         err := CompressImage(thePixMap, trackFrame, theSpaceSettings.spatialQuality, theSpaceSettings.codecType, imageDesc, compressedDataPtr);
  2990.                         err := AddMediaSample(theMedia, compressedData, 0, imageDesc^^.dataSize, myTimeScale, SampleDescriptionHandle(imageDesc), 1, 0, actualTime);
  2991.                     end;
  2992.                 UnlockPixels(thePixMap);
  2993.                 SetGWorld(oldPort, oldGDeviceH);
  2994.                 if (imageDesc <> nil) then
  2995.                     DisposeHandle(Handle(imageDesc));
  2996.                 if (compressedData <> nil) then
  2997.                     DisposeHandle(Handle(compressedData));
  2998.  
  2999.                 err := EndMediaEdits(theMedia);
  3000.                 err := InsertMediaIntoTrack(theTrack, 0, 0, GetMediaDuration(theMedia), fixed1);
  3001.  
  3002.                 err := AddMovieResource(theMovie, resRefNum, resID, fname);
  3003.                 if (resRefNum <> 0) then
  3004.                     err := CloseMovieFile(resRefNum);
  3005.                 DisposeMovie(theMovie);
  3006.  
  3007.                 CurrentSlice := SaveCS;
  3008.                 SelectSlice(CurrentSlice);
  3009.                 title := fname;
  3010.                 PictureType := PicsFile;
  3011.                 UpdateTitleBar;
  3012.  
  3013.                 UpdateWindowsMenuItem;
  3014.                 pmForeColor(ForegroundIndex);
  3015.                 pmBackColor(BackgroundIndex);
  3016.             end; {with}
  3017.     end;
  3018.     
  3019.     
  3020.  
  3021. end.